Extracting specific part of JSON respose on iPhone - iphone

I'm looking at adding a distance calculator to my application. I have been looking at Google's API put i cant seem to decode the JSON. I have managed to do so with PHP. The code for that was:
substr($convertedtoarray['routes']['0']['legs']['0']['distance']['text'], 0, -3);
On the iPhone i managed to get the JSON response but can't get the specific part of it that I want.
Json address: http://maps.googleapis.com/maps/api/directions/json?origin=plymouth&destination=pl210bp&sensor=false
NSMutableDictionary *luckyNumbers = [responseString JSONValue];
[responseString release];
if (luckyNumbers != nil) {
NSString *responseStatus = [luckyNumbers objectForKey:#"routes"];'
}
Where would I go from here?
Any help would be great cheers

NSString *responseStatus = [[[[[[luckyNumbers objectForKey:#"routes"]objectAtIndex:0] objectForKey:#"legs"]objectAtIndex:0] objectForKey:#"distance"] objectForKey:#"text"];
Very ugly you can extract in separate objects like this:
NSArray *routesArray = [luckyNumbers objectForKey:#"routes"];
NSDictionary *firstRoute = [routesArray objectAtIndex:0];
NSArray *legsArray = [firstRoute objectForKey:#"legs"];
NSDictionary *firstLeg = [legsArray objectAtIndex:0];
NSDictionary *distanceDict = [firstLeg objectForKey:#"distance"];
NSString *distanceText = [distanceDict objectForKey:#"text"];
Good luck.

The easiest thing to do would be to create a dictionary iterator, and loop over what children the luckynumbers dictionary has, you can print out, or debug, to see what the keys for these children are, and what object types they are.
I used this technique a few times to figure out what the structure of an XML doc I was being returned was like.

Related

parsing JSON response from server in same order in ios

i have an app which fetches JSON response from server. the JSON response from server looks as follows:
{"status":"SUCCESS","message":"XYZ","token":"ABCDEFGHIJ"}
now i need to store this in a NSDictionary for further parsing. so i use the following approach:
urldata1=[NSURLConnection sendSynchronousRequest:theRequest returningResponse:&res error:nil]; NSDictionary
*myDictionary=[NSJSONSerialization JSONObjectWithData:urldata1 options:NSJSONReadingMutableContainers error:nil];
}
but now the dictionary i get looks as follows:
{
message = "XYZ";
status = SUCCESS;
token = "ABCDEFGHIJ";
}
So i see that the dictionary has been sorted on the basis of keys... is there a way to reproduce the exact same response from server in my dictionary..
It doesn't matter in what order the NSDictionary is because you retrieve the object from the dictionary with keys.
So if you want to access the status first use this code
NSString *status = [myDictionary objectForKey#"status"];
NSString *message = [myDictionary objectForKey#"message"];
NSString *token = [myDictionary objectForKey#"token"];
And you can access a Dictionary inside a Dictionary like this
NSDictionary *dict= [myDictionary objectForKey#"SomeOtherDictionary"];
Sorting a dictionary is meaningless. You need to first create an array which will sort according to your needs.
You can refer Sorting NSDictionary from JSON for UITableView for further explanations.

Converting an NSArray of Dictionaries to JSON array in iOS

I need to send an NSArray to the server in the JSON array format. How can I convert it to JSON. This is a sample of my NSArray that I have to pass.
array([0] => array('latitude'=>'10.010490',
'longitude'=>'76.360779',
'altitude'=>'30.833334',
'timestamp'=>'11:17:23',
'speed'=>'0.00',
'distance'=>'0.00');
[1] => array('latitude'=>'10.010688',
'longitude'=>'76.361378',
'altitude'=>'28.546305',
'timestamp'=>'11:19:26',
'speed'=>'1.614',
'distance'=>'198.525711')
)`
and the required format is like this
[
{ "latitude":"10.010490",
"longitude":"76.360779",
"altitude":"30.833334",
"timestamp":"11:17:23",
"speed":"0.00",
"distance":"0.00"
},
{
"latitude":"10.010688",
"longitude":"76.361378",
"altitude":"28.546305",
"timestamp":"11:19:26",
"speed":"1.614",
"distance":"198.525711"
}
]
Any one have solution? Thanks in advance.
NSDictionary *firstJsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"10.010490", #"latitude",
#"76.360779", #"longitude",
#"30.833334", #"altitude",
#"11:17:23", #"timestamp",
#"0.00", #"speed",
#"0.00", #"distance",
nil];
NSDictionary *secondJsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"10.010490", #"latitude",
#"76.360779", #"longitude",
#"30.833334", #"altitude",
#"11:17:23", #"timestamp",
#"0.00", #"speed",
#"0.00", #"distance",
nil];
NSMutableArray * arr = [[NSMutableArray alloc] init];
[arr addObject:firstJsonDictionary];
[arr addObject:secondJsonDictionary];
NSData *jsonData2 = [NSJSONSerialization dataWithJSONObject:arr options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData2 encoding:NSUTF8StringEncoding];
NSLog(#"jsonData as string:\n%#", jsonString);
The simplest and best approach !!!
To convert NSArray or NSMutableArray into jsonString you can first convert it into NSData and then further convert that into a NSString. Use this code
NSData* data = [ NSJSONSerialization dataWithJSONObject:yourArray options:NSJSONWritingPrettyPrinted error:nil ];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
It helped me and hope it helps you as well. All the best.
I would recommend the SBJson-Framework.
Converting an NSMutableArray is as simple as NSString *jsonString = [yourArray JSONRepresentation];
Edit: Jack Farnandish is right u have to transform it into a NSDictionary before you can convert it to Json. In my example the NSMutableArray has to contain the Dictionary. The Array is only needed to create the square brackets at the beginning and the end of the string.
You can use the build in JSON functions of iOS or use an external lib e.g. JSONKit to convert your data to JSON
First You must change you structure into NSDictionary class and NSArray containing NSDictionary objects, then try JSONKit in iOS 5 serialization works better than standard NSJSONSerialization.
#import <JSONKit/JSON.h>
NSArray *array = // Your array here.
NSString *json = [array JSONString];
NSLog(#"%#", json);
JSONKit performs significantly better than SBJson and others in my own and the author's benchmarks.
Check this tutorial, JSON in iOS 5.0 was clearly explained (serailization, deserailization).
Is the service you are calling a RESTful service?
If so, I'd strongly recommend using RestKit. It does object serialization/deserialization. It also handles all the networking underpinnings. Extremely valuable, and well maintained.

Help needed with json iphone

I m receiving data from the server. Now when i m deserializing it i m getting an array with key value. Now the first object of the array is my whole NSDictionary item from which i have to extract data using keys. I m stuck here i tried using different things like extracting them in sets but it disturbs there arrangement. I m pretty new in the field . please can anyone help me out here. How to get that array into a NSDictionary object or extract info using keys from that array. Thanks.
NSData *responseData = [[request responseString] dataUsingEncoding:NSUTF8StringEncoding];
NSError *err = nil;
NSDictionary *dataArray = [[CJSONDeserializer deserializer]deserialize:responseData error:&err];
it gves an array as output to me.
How about: NSDictionary *myDictionary = [myArray objectAtIndex:0];
I highly recommend the SBJson framework as a production ready library for dealing with just such issues.

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]];
}

Plist not saving from dictionary (to Documents)

I've been trying to save a plist of a NSDictionary to my app's Documents folder. I haven't tried this on the device yet but I'd like it to work on the simulator for testing purposes. The [self createDictionaryFromChoreList] method just creates a NSDictionary from some data in another class of mine. I've pretty much copied/pasted this code from the web documents and when I go to see if the file was saved or not, I find that it isn't. Here is the method block.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistName = [[NSString alloc] initWithFormat:#"%#chores.plist", self.firstName];
NSString *path = [documentsDirectory stringByAppendingPathComponent:plistName];
NSDictionary *choresDictionary = [[NSDictionary alloc] initWithDictionary:[self createDictionaryFromChoreList]];
[choresDictionary writeToFile:path atomically:YES];
Any help is greatly appreciated. Thanks in advance.
-S
You should also capture the BOOL returned by writeToFile:atomically:. That will tell you if the write succeeded or not.
Also, are you sure you are looking in the right documents folder? If you have more than one app in the simulator its easy to open the wrong app's documents folder in the Finder. I did that once and it cost me a couple of hours of frustration.
Edit01:
writeToFile:atomically: returning false explains why no file exist. The simplest explanation is that something in the dictionary is not a property list object.
From the NSDictionary docs:
This method recursively validates that
all the contained objects are property
list objects (instances of NSData,
NSDate, NSNumber, NSString, NSArray,
or NSDictionary) before writing out
the file, and returns NO if all the
objects are not property list objects,
since the resultant file would not be
a valid property list.
It just takes one non-plist object buried deep in a dictionary to prevent it from being converted to a plist.
Don't forget serialize the plist data:
Here is a snippet of code that I use for writing information to a plist
NSString *errorString;
NSData *data = [NSPropertyListSerialization dataFromPropertyList:plistDict
format:NSPropertyListXMLFormat_v1_0
errorDescription:&errorString];
[plistDict release];
if (!data) {
NSLog(#"error converting data: %#", errorString);
return NO;
}
if ([data writeToFile:[XEraseAppDelegate loadSessionPlist] atomically: YES]) {
return YES;
} else {
NSLog(#"couldn't write to new plist");
return NO;
}
This is something I whipped up really quickly and it correctly writes a plist directory of name and company to the documents directory. I have a feeling your dictionary creation method might have an issue. Try this out for yourself, then add your code and make sure it works.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *plistDirectory = [paths objectAtIndex:0];
NSString *plistPath = [plistDirectory stringByAppendingPathComponent:#"userCompany.plist"];
NSArray *userObjects = [[NSArray alloc] initWithObjects:#"Joe", #"Smith", #"Smith Co", nil];
NSArray *userKeys = [[NSArray alloc] initWithObjects:#"First Name", #"Last Name", #"Company", nil];
NSDictionary *userSettings = [[NSDictionary alloc] initWithObjects:userObjects forKeys:userKeys];
[userSettings writeToFile:plistPath atomically:YES];
Is it correct, that the name of file your writing to is:
SOEMTHINGchores.plist?
Created via:
NSString *plistName = [[NSString alloc] initWithFormat:#"%#chores.plist", self.firstName];
Also, what is the output of:
[choresDictionary print];
Some additional info would help to debug this.
Where exactly are you looking for the file?
I have the exact same code and it works fine for me.
Just that I have to dig deep to get the file. Something like:
/Users/myUserName/Library/Application Support/iPhone Simulator/User/Applications/0E62A607-8EEB-4970-B198-81CE4BDDB7AA/Documents/data.plist
And the HEX number in the path changes with every run. So I print the file path with every run.
Insert a break point at
NSDictionary *choresDictionary = [[NSDictionary alloc] initWithDictionary:[self createDictionaryFromChoreList]];
now when you step out drag your mouse over choresDictionary and check in the tooltip that its size is not 0x0 or you can simply do an NSLog of the choresDictionary
like NSLog(#"%#",choresDictionary); I think your dictionary has 0 key key value pairs thats why you are getting null into your documents folder.
Thanks,
Madhup
I was running into this issue as well. In my case it turned out that I was using NSNumbers for keys - which is not valid.