Trouble correctly formatting NSString for JSON - iphone

Having a little trouble processing my NSStrings into a valid JSON string.
NSString *version = #"1.1";
NSString *callMethod = #"auth.login";
NSString *paramsConfig = [NSString stringWithFormat:#"{\"email\":\"%#\",\"password\":\"%#\"}", usernameString, passwordString];
int queryId = arc4random()% 10000000;
NSDictionary *userData = [NSDictionary dictionaryWithObjectsAndKeys:version, #"version", callMethod, #"method", [NSNumber numberWithInt:queryId], #"id", paramsConfig, #"params", nil];
NSString* jsonString = [userData JSONRepresentation];
Expected JSON string:
{"version":"1.1","params":"{"email":"s","password":"s"}","id":12345678,"method":"auth.login"}
Actual JSON string:
{"version":"1.1","params":"{\"email\":\"s\",\"password\":\"s\"}","id":12345678,"method":"auth.login"}
Not really sure where I'm going wrong. Any thoughts?
Thanks
Sam

The paramsConfig part of your JSON is a string, and will be escaped as such. IIRC, if you change paramsConfig to be a NSDictionary, then set the values for email and password there, the correct JSONRepresentation will be outputted.

Related

How to Parse this JSON in Objective-C

I'm new in iPhone programming.
I have to parse this data in JSON in Objective-C.
{"success":1,"check":[{"ChkKey":"2","ChkDeb":"Connection 1","ChkSSID":"Netgear-1111","ChkIP":"192.168.2.103","ChkBlk":"0"}]}
I follow the example for parsing data with Json. But this JSON is so different.
It is composed by two Array.
How can i proceed?
Thanks - A.b.
How about trying something like this ...
//JSON string
NSString *jsonString = #"{\"success\":1,\"check\":[{\"ChkKey\":\"2\",\"ChkDeb\":\"Connection 1\",\"ChkSSID\":\"Netgear-1111\",\"ChkIP\":\"192.168.2.103\",\"ChkBlk\":\"0\"}]}";
//Parse JSON string into an NSDictionary
NSError *e = [[NSError alloc] init];
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&e];
//Output the value of success
NSLog(#"Success:%#", [jsonData objectForKey:#"success"]);
//Get data in the check array
NSDictionary *checkData = [[jsonData objectForKey:#"check"] objectAtIndex:0];
//Output the value of ChkSSID
NSLog(#"ChkSSID:%#", [checkData objectForKey:#"ChkSSID"]);

JSONKit: changing and serializing JSON attribute's value

I am using JSONKit to parse JSON string into NSDictionary:
NSDictionary *deserializedData = [jsonString objectFromJSONString];
My question is: how can I change the dictionary values and get a changed JSON String?
I've tried to change the dictionary values:
[deserializedData setObject:[NSNumber numberWithInt:iRatings] forKey:#"ratings"];
But the app crashes in that line. What am I doing wrong?
Thanks in advance!
While the other answers are correct, what you really want in this case is:
NSMutableDictionary *deserializedData = [jsonString mutableObjectFromJSONString];
The mutableObjectFromJSONString method will create a mutable dictionary directly, which saves time and memory.
NSDictionary is an immutable dictionary, you need NSMutableDictionary to change the data. I'm not sure about JSONKit, but the built-in Cocoa JSON parser has a flag to return the data in mutable containers.
In worst case, you can do something like that:
NSMutableDictionary* data = [NSMutableDictionary dictionaryWithDictionary:[jsonString objectFromJSONString]];
[data setObject:[NSNumber numberWithInt:iRatings] forKey:#"ratings"];
//
// we begin with our string in json format
//
NSString *jsonString = [[NSString alloc] initWithString:#"{\"1\":\"Hole 1: Rossy Robinson - $25\",\"2\":\"Hole 7: Davey Ambrose - $25\",\"3\":\"Hole 14: Ross Robinson - $25\"}"];
//
// convert the json string to an NSMutableDictionary
//
NSError *e;
NSMutableDictionary *JSONdic = [NSJSONSerialization JSONObjectWithData: [jsonString dataUsingEncoding: NSUTF8StringEncoding] options: NSJSONReadingMutableContainers error: &e];
//
// change a value and add a new value in the dict
//
NSLog(#"before: object for key 1 is: %#", [JSONdic objectForKey:#"1"]);
[JSONdic setObject:#"xxx" forKey:#"1"];
[JSONdic setObject:#"Phil McQuitty" forKey:#"2"];
//
//convert dictionary object to json data
//
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:JSONdic options:NSJSONWritingPrettyPrinted error:&e];
//
// convert the json data back to a string
//
NSString *jsonText = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];\
//
// print out the final results
//
NSLog(#"back to string: %#", jsonText);
You try to change an immutableobject.
NSMutableDictionary *deserializedData = [NSMutableDictionary dictionaryWithDictionary: [jsonString objectFromJSONString]];
This is a mutable dictionary and you can change the values in it.
You try like this:
NSMutableDictionary *deserializedData = [NSMutableDictionary dictionaryWithDictionary: [jsonString objectFromJSONString]];
and then change the values:
[deserializedData setObject:[NSNumber numberWithInt:iRatings] forKey:#"ratings"];
For NSDictionary we cannot add or change values, thats why application is crashing.

NSDictionary to XML

I'm trying to convert a NSDictionary to XML. (I was successful in transforming NSDictionary to JSON). But now I need to transform NSDictionary to XML. Is there a built-in serializer in Objective-C like the one for JSON?
int r = arc4random() % 999999999;
//simulate my NSDictionary (to be turned into xml)
NSString *name = [NSString stringWithFormat:#"Posted using iPhone_%d", r];
NSString *stock_no = [NSString stringWithFormat:#"2342_%d", r];
NSString *retail_price = #"12345";
NSArray *keys = [NSArray arrayWithObjects:#"name", #"stock_no", #"retail_price", nil];
NSArray *objects = [NSArray arrayWithObjects:name,stock_no,retail_price, nil];
NSDictionary *theRequestDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSDictionary *theFinalRequestDictionary = [NSDictionary dictionaryWithObject:theRequestDictionary forKey:#"product"];
...//other irrelevant code omitted
NSData *theBodyData = [NSPropertyListSerialization dataFromPropertyList:theFinalRequestDictionary format:NSPropertyListXMLFormat_v1_0 errorDescription:nil];
NSPropertyListFormat format;
id XMLed = [NSPropertyListSerialization propertyListFromData:theBodyData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:nil];
NSLog(#"the XMLed is this: %#", [NSString stringWithFormat:#"%#", XMLed]);
The NSLog doesn't print a string in XML format. It prints it like a NSDictionary.
What should I use to serialize my NSDictionary to XML?
propertyListFromData:... returns a "property list object", that is, depending on the contents of the data, an array or a dictionary. The thing that you're actually interested in (the xml) is returned by dataFromPropertyList:... and thus stored in your theBodyData variable.
Try this:
NSLog(#"XML: %#", [[[NSString alloc] initWithData:theBodyData encoding:NSUTF8StringEncoding] autorelease]);
There are many different varieties of XML. If you're not picky about the specific tags, and if the contents of your dictionary is limited to types used in property lists (NSString, NSNumber, NSDate, etc.) you can write your dictionary to a property list in one line:
[myDict writeToFile:somePath atomically:YES];
If you'd prefer to keep the XML in memory instead of writing to a file, use NSPropertyListSerialization as you're doing.

stringByReplacingOccurrencesOfString not working as expected

Having a problem. Here's my code:
Latitude = [TBXML textForElement:lat]; //Latitude & Longitude are both NSStrings
Longitude= [TBXML textForElement:lon];
NSLog(#"LAT:%# LON:%#",Latitude,Longitude);
NSString *defaultURL = #"http://api.wxbug.net/getLiveWeatherRSS.aspx?ACode=000000000&lat=+&long=-&unittype=1";
newURL = [[defaultURL stringByReplacingOccurrencesOfString:#"+"
withString:Latitude]
stringByReplacingOccurrencesOfString:#"-"
withString:Longitude];
NSLog(#"%#",newURL);
And here's the output:
LAT:-33.92 LON:18.42
http://api.wxbug.net/getLiveWeatherRSS.aspxACode=000000000&lat=18.4233.92&long=18.42&unittype=1
As you can see, something strange is happening to the appending code. Am I doing something wrong here?
Before replacing the longitude, the string is
http://....&lat=-33.92&long=-&...
^ ^
The system sees that there are two -, and thus both of them will be replaced by the latitude.
You should use a more descriptive string to replace with, e.g.
NSString *defaultURL = #"http://....&lat={latitude}&long={longitude}&unittype=1";
newURL = [defaultURL stringByReplacingOccurrencesOfString:#"{latitude}"
withString:Latitude];
newURL = [newURL stringByReplacingOccurrencesOfString:#"{longitude}"
withString:Longitude];
or simply use +stringWithFormat:.
NSString* newURL = [NSString stringWithFormat:#"http://....&lat=%#&long=%#&...",
Latitude, Longitude];
Here's where we started:
url = #"http://...?ACode=000000000&lat=+&long=-&unittype=1"
Latitude = #"-33.92"
Longitude = #"18.42"
Then you replaced all occurrences of #"+" with #"-33.92":
url = #"http://...?ACode=000000000&lat=-33.92&long=-&unittype=1"
Then you replaced all occurrences of #"-" with #"18.42". Note that there are two '-' characters; one after lat= and one after long=. The one after 'lat' is there because the string you pasted in had a - in it.
url = #"http://...?ACode=000000000&lat=18.4233.92&long=18.42&unittype=1"
Thus, your final result.
#KennyTM, BJ Homer, and madmik3 are correct. Your value is getting replaced twice.
However, you should technically be building your URL in a totally different manner:
NSMutableDictionary *query = [NSMutableDictionary dictionary];
[query setObject:#"000000000" forKey:#"ACode"];
[query setObject:Latitude forKey:#"lat"];
[query setObject:Longitude forKey:#"long"];
[query setObject:#"1" forKey:#"unittype"];
NSMutableArray *queryComponents = [NSMutableArray array];
for (NSString *key in query) {
NSString *value = [query objectForKey:key];
key = [key stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
value = [value stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *component = [NSString stringWithFormat:#"%#=%#", key, value];
[queryComponents addObject:component];
}
NSString *queryString = [components componentsJoinedByString:#"&"];
NSString *fullURLString = [NSString stringWithFormat:#"http://api.wxbug.net/getLiveWeatherRSS.aspx?%#", queryString];
NSURL *newURL = [NSURL URLWithString:fullURLString];
(ignoring the efficacy of -stringByAddingPercentEscapesUsingEncoding: for now)
The reason this is better is that according to the HTTP specification, the keys and values in the query of the URL should be URL encoded. Granted, you're only encoding numbers for simple keys. But if that ever changes, you URL might break. (The flaw with this method is that it only allows a single value per key, and the HTTP spec allows you to specify multiple values. For the sake of simplicity, I've left that out)
There are also some issues on using -stringByAddingPercentEscapesUsingEncoding:. For more information on that, check out Objective-c iPhone percent encode a string?.
Your LAT is negative. So the - gets replaced twice.

how to retrieve a substring from a string?

I am doing Fconnect in that when a user connects to facebook I get a string like this
{"id":"100001480456987","name":"Vishnu Gupta","first_name":"Vishnu","last_name":"Gupta","link":"http:\/\/www.facebook.com\/profile.php?id=100001480456987","education":[{"school":{"id":"110885222265513","name":"st.joseph"},"type":"High School"}],"gender":"male","email":"vishu.gupta20#gmail.com","timezone":5.5,"locale":"en_US","verified":true,"updated_time":"2010-11-27T10:10:25+0000"}
Now I want to split the id name and email id of the user so that I can store it in my database.
Can someone tell me how to do it????
You don't want to split a string to get those values. Instead, you want to parse the JSON to grab data. I've used this library, it works very well: http://stig.github.com/json-framework/
Hope this helps!
EDIT: Some sample code:
NSDictionary *dict = [responseFromFacebook JSONValue];
NSString *facebookID = [dict objectForKey:#"id"];
NSString *name = [dict objectForKey:#"name"];
NSString *email = [dict objectForKey:#"email"];
this looks like JSON. Some information on JSON handling with Objective C is available at
http://blog.zachwaugh.com/post/309924609/how-to-use-json-in-cocoaobjective-c
Use a JSON parser. See this answer for links to stackoverflow questions about the different JSON libraries available.
Of course I'd also like to mention my own JSON parsing library, JSONKit. At the time of this writing I think it's fair to say that it's the fastest JSON parser out there.
Try this
NSDictionary *dict=[[NSDictionary alloc]init];
string=[string stringByReplacingOccurrencesOfString:#"{" withString:#""];
string=[string stringByReplacingOccurrencesOfString:#"}" withString:#""];
string=[string stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSArray *seperated=[string componentsSeparatedByString:#","];
for(int index=0;index<[seperated count];index++)
{
NSArray *sub=[[seperated objectAtIndex:index] componentsSeparatedByString:#":"];
[dict setValue:[sub objectAtIndex:0] forKey:[sub objectAtIndex:1]];
}