How to parse NSDictionary sequentially? - ios

I need to parse a json and get the key value pairs in the same sequence as they are present in response.
Currently what i'm doing is
-(instancetype)initWithJson:(NSDictionary *)responseDict {
if (self = [super init]){
NSArray *tempArray = [[NSArray alloc] init];
NSArray *roomSizesForAcArray = [responseDict valueFromDictionaryWithNSNullCheck:#"roomSizesForAc"];
NSArray *loadChartForInverterArray = [responseDict valueFromDictionaryWithNSNullCheck:#"loadChartForInverter"];
if(roomSizesForAcArray && roomSizesForAcArray.count>0){
self.isInverterChart=false;
tempArray=roomSizesForAcArray;
}
else if(loadChartForInverterArray && loadChartForInverterArray.count>0){
self.isInverterChart=true;
tempArray=loadChartForInverterArray;
}
self.arrayOfChartSizeObjects=tempArray;
if(tempArray && tempArray.count>0){
//Temp array first object is a dictionary which i need to parse sequentially
self.arrayOfKeys = [[tempArray objectAtIndex:0] allKeys];
//This array of keys is random every time and not sequential
}
}
return self;
}
I need to someway parse the dictionary [tempArray objectAtIndex:0] maintaining the order of keys in init.

Not clear what you want, you want dictionary while you are already parsing the dictionary. To get dictionary from the JSON use below code.
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:receiveData options:kNilOptions error:&error];
To get all the keys and then retrieve the details use
NSArray *sortedKeys = [[jsonDict allKeys]
Once you have keys then get the details

NSError *e = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &e];
if (!jsonArray) {
NSLog(#"Error parsing JSON: %#", e);
} else {
for(NSDictionary *item in jsonArray) {
NSLog(#"Item: %#", item);
}
}

Dictionaries are unordered collections. You say "...maintaining the order of keys in init". There is no such thing.
JSON "Objects", the JSON equivalent of a NSDictionaries/Swift Dictionaries, have the same issue.
Some JSON libraries will preserve the order in which key/value pairs are submitted to be sent, but you should not depend on that. The JSON protocol does not guarantee it.
Once you receive JSON data and convert it to an NSDictionary/Dictionary, the order in which the key/value pairs is sent is lost. The only way I know of to preserve the (already unreliable) order of the key/value pairs from the original JSON data stream is to parse the JSON yourself rather than deserializing it using NSJSONSerialization.
If you want your data in a particular order, you should use an array as the container object to send it. You can send an array of key/value pairs if you need to.

Related

Single object json parse - what am I doing wrong?

This has got to be something obvious that I am doing wrong. I have been banging my head against a wall trying to figure out what is going on. I already have this json parsing done in the android version of my app, now trying to parse this simple json in xcode and can't get it done.
NSError *myError = nil;
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:self.responseData options:kNilOptions error:&myError];
NSLog([res objectForKey:#"Date"]);
This code get me the "unrecognized selector sent to instance" error.
Here is the json data and you can see Date is one of the objects:
[{"Date":"2016-06-17T22:56:33.0811255-05:00"}]
Thanks in advance for any help on this issue. I've tried to simplify this post, but if more info is needed I will try and quickly provide.
http://i.stack.imgur.com/Y5fsT.png
JSONObjectWithData is returning an array of dictionaries and not a dictionary. Your print out of the raw JSON confirms this:
[{"Date":"2016-06-17T22:56:33.0811255-05:00"}] // This is an array
However you're attempting to treat that response object like a dictionary. In doing so you're calling a dictionary method (objectForKey:) on an array. This results in a crash. Try something like this:
NSError *error = nil;
id responseObject = [NSJSONSerialization JSONObjectWithData:self.responseData options:kNilOptions error:&error];
if (error)
{
// Handle error
return;
}
NSLog(#"%#", responseObject);
if ([responseObject isKindOfClass:[NSArray class]])
{
NSArray *responseArray = (NSArray *)responseObject;
for (id item in responseArray)
{
NSLog(#"%#", item);
if ([item isKindOfClass:[NSDictionary class]])
{
NSDictionary *dictionary = (NSDictionary *)item;
NSString *dateString = [dictionary objectForKey:#"Date"];
NSLog(#"%#", dateString);
}
}
}
else
{
// responseObject is not an array...
}
I'm pretty sure this is because you should first set res as [NSDictionary]. Then pick the first element in that array and then get objectForKey: "Date". Normal JSON Data starts with a {, this starts with a [. Which means it's an array.
You can see it for yourself in the screenshot when it says #: 1 Element . THEN it says 1 key/value pair. The NSDictionary is inside an array.NSError
Try this code:
*myError = nil;
[NSDictionary] *res = [NSJSONSerialization JSONObjectWithData:self.responseData options:kNilOptions error:&myError];
if (res.count > 0) {
NSLog([res[0] objectForKey:#"Date"]);
}

Getting one value from JSON API in Objective-C

I'm trying to get one value from JSON. JSON is located in NSString and it looks like this:
{"coord":{"lon":-122.38,"lat":37.57},"weather":[{"id":300,"main":"Drizzle","description":"Lekka mżawka","icon":"09d"}],"base":"stations","main":{"temp":304.74,"pressure":1017,"humidity":35,"temp_min":300.15,"temp_max":307.59},"visibility":16093,"wind":{"speed":6.7,"deg":250},"clouds":{"all":75},"dt":1437346641,"sys":{"type":1,"id":478,"message":0.0615,"country":"US","sunrise":1437311022,"sunset":1437362859},"id":5357155,"name":"Hillsborough","cod":200}
I'm interested in getting "temp". How should I do that?
Assuming your JSON string was stored as a NSString named JSONString:
NSError *error;
NSDictionary *keys = [NSJSONSerialization JSONObjectWithData:[JSONString dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error:&error];
NSLog(#"temp = %#", keys[#"main"][#"temp"]); // temp = 304.74
To get the main sub item in weather, which is an array with multiple items, you should point out its index to tell the selector which object in the array is the one you are looking for. In this case, it's 0:
NSLog(#"weather = %#", keys[#"weather"][0][#"main"]); // weather = Drizzle

IOS Dev Fetching JSON Data

I am a novice at IOS dev and i really need some help.
I want to parse (which is working) and fetch some JSON Data.
i used this tutorial for the http request and json parsing
http://www.mysamplecode.com/2013/04/ios-http-request-and-json-parsing.html
everything works fine with a 1 dimensional dictionary
but I need to be able to fetch the following JSON Data
[{"defaultGateway": "10.10.10.254", "hostname": "On", "connected": "true", "subnetMask": "255.255.255.255", "iPAddress": "10.10.10.10", "dhcpEnabled": "true"},
{"defaultGateway": "10.10.10.254", "hostname": "On", "connected": "true", "subnetMask": "255.255.255.255", "iPAddress": "10.10.10.10", "dhcpEnabled": "true"}]
after I use the following function I got the following dictionary which I really don't know how to access
NSDictionary * res = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
here is a picture of the dictionary
http://www11.pic-upload.de/09.11.14/5n4hdg3eh84q.png
How can I access for example the defaultGateway in the first dictionary?
You have a small logical error in your example. The expression [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error]; returns an NSArray and not and NSDictionary. So, first you should change this part to:
NSArray *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
I know it's an array because your JSON string contains an array of two JSON objects. NSJSONSerialization will transform JSON arrays into objects of type NSArray and JSON objects into objects of type NSDictionary.
If you're not sure what your JSON contains, you can do the following:
id result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if ([result isKindOfClass:[NSArray class]]){
// do something with the array
}
else if ([result isKindOfClass:[NSDictionary class]]){
// do something with the dictionary
}
As for your question, you can access the data in an NSDictionary by providing a key, which you can do in two ways:
NSString *gateway = [dictionary objectForKey:#"defaultGateway"];
or even faster:
NSString *gateway = dictionary[#"defaultGateway"];
Coming back to your example, to access the defaultGateway from the first of your two JSON objects, you can do the following:
NSArray *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error]; // parse the JSON and store in array
NSDictionary *dict = result[0]; // take the first of the two JSON objects and store it in a dictionary
NSString *gateway = dictionary[#"defaultGateway"]; // retrieve the defaultGateway property

Convert NSArray into array of JSON objects

I'd like to create a JSON array of objects from the resultsArray.
NSMutableArray *resultsArray = [NSMutableArray array];
FMResultSet *resultsSet = [database executeQuery:queryString];
while ([resultsSet next]) {
[resultsArray addObject:[resultsSet resultDictionary]];
}
For clarification, I'm using FMDB to query a database. I'm then storing the resulting objects within the resultsArray. From here I want to convert that results array into a JSON array of objects.
You can use NSJSONSerialization class to create a JSON file from your dictionary using the class method
NSData * JSONData = [NSJSONSerialization dataWithJSONObject:resultsArray
options:kNilOptions
error:&error];
For more info look at apple documentation

object returned from NSJSONSerialization can vary

Is the following statement correct, or am I missing something?
You have to check the return object of NSJSONSerialization to see if it is a dictionary or an array - you can have
data = {"name":"joe", "age":"young"}
// NSJSONSerialization returns a dictionary
and
data = {{"name":"joe", "age":"young"},
{"name":"fred", "age":"not so young"}}
// returns an array
Each type has a different access method which breaks if used on the wrong one.
For example:
NSMutableArray *jsonObject = [json objectAtIndex:i];
// will break if json is a dictionary
so you have to do something like -
id jsonObjects = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers error:&error];
if ([jsonObjects isKindOfClass:[NSArray class]])
NSLog(#"yes we got an Array"); // cycle thru the array elements
else if ([jsonObjects isKindOfClass:[NSDictionary class]])
NSLog(#"yes we got an dictionary"); // cycle thru the dictionary elements
else
NSLog(#"neither array nor dictionary!");
I had a good look thru stack overflow and Apple documentation and other places and could not find any direct confirmation of the above.
If you are just asking if this is correct or not, yes it is the safe way to process jsonObjects. It's also how you would do it with other API that returns id.

Resources