Parsing JSON in Objective C with key names as incremented integers - ios

not really sure how to even word this question BUT I have some JSON that I need to parse which is formatted like so:-
"nodes": {
"4": {
"node_id": 4,
"title": "TITLE 1",
"description": "",
},
"7": {
"node_id": 7,
"title": "TITLE 2",
"description": "",
},
"12": {
"node_id": 12,
"title": "TITLE 3",
"description": "",
},
Normally I would grab values with the standard [dictionary objectForKey#"key"] but as the items begin with an integer (string) I am finding it hard to parse correctly. Am I missing something really simple here?

If you just want to access one value than you would do the following.
// Assume JSONObject is the "root" dictionary
NSDictionary *fourDictionary = JSONObject[#"nodes"]["4"] // This will get the object from "4":{}
Now if the JSON in question can have a dynamic number of objects than this is much trickier. The easiest solution would be to get the provider of the JSON to rewrite it as an array of objects. You could than look up the object you want using the object's node_id value.
If this is not possible than you could attempt to write a for loop to loop through all of the keys in the "nodes" object and access the items from the dictionary that way.
i.e.
NSMutableArray *arrayOfNodes = [NSMutableArray array];
NSDictionary *nodes = JSONObject[#"nodes"];
for(NSString *numberKey in [nodes allKeys])
{
NSDictionary *nodeObject = nodes[numberKey]
[arrayOfNodes addObject:nodeObject];
}
// Do anything else with the nodes now that they are in an array.

Related

I am trying to parse such a json in which use many arrays and dictionary. How to parse it in iOS?

I'm able to parse first three values. The nested values in dayWiseTimeSheet section i want to parse.
{"TimeSheet":
[
{"day":"10-5-2016",
"totalTravelTime":"1.40hrs",
"totalWorkTime":"6hrs",
"dayWiseTimeSheet": [{
"taskId": "101",
"travelingTime": "40 mins",
"workingTime": "3 hrs"
}, {
"taskId": "102",
"travelingTime": "1 hr",
"workingTime": "3 hrs"
}]
},
{"day":"11-5-2016",
"totalTravelTime":"1.40hrs",
"totalWorkTime":"6hrs",
"dayWiseTimeSheet": [{
"taskId": "101",
"travelingTime": "50 mins",
"workingTime": "5 hrs"
}, {
"taskId": "102",
"travelingTime": "3 hr",
"workingTime": "7 hrs"
}]
}
]
}
The code i have used is
for (NSDictionary *bpDictionary in books )
{
TimesheetInfo *tableObject = [[TimesheetInfo alloc]initwithday:
[bpDictionary objectForKey:#"day"]
totalTravelTime:[bpDictionary objectForKey:#"totalTravelTime"]
totalWorkTime:[bpDictionary objectForKey:#"totalWorkTime"]
}
Please try this :
NSMutableArray *allDayWiseTimeSheet = [NSMutableArray new];
for (NSDictionary *bpDictionary in books )
{
TimesheetInfo *tableObject = [[TimesheetInfo alloc]initwithday:[bpDictionary objectForKey:#"day”]]]
totalTravelTime:[bpDictionary objectForKey:#"totalTravelTime"]
totalWorkTime:[bpDictionary objectForKey:#"totalWorkTime"]
NSArray *dayWiseTimeSheet = [bpDictionary objectForKey:#“dayWiseTimeSheet”];
for(NSDictionary *info in dayWiseTimeSheet)
{
[allDayWiseTimeSheet addObject:info];
NSLog(#“%#”,[info valueForKey:#“taskId”]);
NSLog(#“%#”,[info valueForKey:#“travelingTime”]);
NSLog(#“%#”,[info valueForKey:#“workingTime”]);
}
}
Parse the 3rd Key's Value into a dictionary with Data Type of Array with Anyobject Data Type
Later get every object from array into a entity class.
Let dict = response.objectforkey("dayWiseTimeSheet")
if the data is a json ,maybe you must translate the json to nsdictionary ,then you can get the NSarry for the collecttion of model.
Given the JSON data the following code will parse "dayWiseTimeSheet" data. The type of the json should be dictionary not an array.
for (id obj in [[json valueForKey:#"TimeSheet"] valueForKey:#"dayWiseTimeSheet"]) {
NSLog(#"%#",[obj valueForKey:#"taskId"]);
NSLog(#"%#",[obj valueForKey:#"travelingTime"]);
NSLog(#"%#",[obj valueForKey:#"workingTime"]);
}

CoreData fetch nested objects

I have a json which contain objects where each object have child object, for example
[
{
"id": 1,
"name": "obj1"
},
{
"id": 2,
"name": "obj2"
},
{
"id": 3,
"name": "obj3",
"child": {
"id": 2,
"name": "obj2"
}
},
{
"id": 4,
"name": "obj4",
"child": {
"id": 5,
"name": "obj5"
}
}
]
So in core data i have entity MyObject which has relation to child (to itself, to one), and relation to parent (to many)
So when i try fetch object by predicate like
[NSPredicate predicateWithFormat:#"parent.#count = 0"]
I got only object with id in [1,3,4], but no with id = 2 (here error) and id = 5 (here all correct), because it's was sets parent when it's mapped when object with id = 3 save to data base.
If no use predicate i got 5 object, include obj5.
But i need fetch from coredata exactly count of object what i got from json.
I need fetch only object with id in [1,2,3,4].
How do i need write predicate, if it's possible?
The data you got from JSON is a subset of all your objects, but the logic according to which it is selected is not persisted in your object model.
You persist the relationship between child and parent (hint: for readability, rename it as parents if it is to-many), but the selection in your JSON example is not based on any of those criteria.
One easy way to get all the objects is to extract the top level ids delivered by the JSON feed and use that in the predicate:
NSArray *ids = [jsonArray valueForKey:#"id"];
[NSPredicate predicateWithFormat:#"idNumber in %#", ids];
(Note that I changed your attribute name from id to idNumber in order to avoid possible language quirks, as id is a reserved word.)

How to create a NSDictionary with blank key/ without key for an object

I want to create a JSON string from a NSDictionary.The complete JSON to create is given below.
{
"source":"point a ",
"destination":"point b ",
"boardingPoint":{
"id":"2222",
"location":"Some location"
},
"customerName":"test",
"customerLastName":"testing",
"customerEmail":"test#gmail.com",
"blockSeatPaxDetails":[
{
"age":"20",
"name":"test123",
"sex":"M",
"title":"Mr",
"email":"testing#gmail.com"
}
],
"inventory":0
}
Now I am stuck at creating dictionary for the first part of this JSON ie
{
"source": "point a ",
"destination": "point b ",
"boardingPoint": {
"id": "2222",
"location": "Some location",
},
Here the boardingPoint is a dictionary which is added to one dictionary.And then along with rest of the keys I make a final dictionary.So when I create the final dictionary, with objectsAndKeys I have no key to set for the first part which is shown below.If I set blank like this #" " the JSON string shows " " as key.And ofcourse I cannot use nil.How to do it then?
This is how it apppears if I insert blank as key for the first part
{
"" : {
"source" : "point a",
"boardingPoint" : {
"id" : "2222",
"location" : "Some location",
},
"destination" : "point b"
},
This is how I create the dictionaries
NSDictionary *boardingPoint = [NSDictionary dictionaryWithObjectsAndKeys:boardingPointID,#"id", boardingLocation,#"location",nil];
NSDictionary *firstDictionary = [NSDictionary dictionaryWithObjectsAndKeys:source,#"source",dest,#"destination",nil];
NSDictionary *mainDictionary = [NSDictionary dictionaryWithObjectsAndKeys:firstDictionary, #" ",customerName,#"customerName",customerLastName,#"customerLastName",customerEmail,#"customerEmail",blockSeatPaxDetails,#"blockSeatPaxDetails",inventory,#"inventory",nil];
and then ofcourse
NSData *finalData = [NSJSONSerialization dataWithJSONObject:mainDictionary options:NSJSONWritingPrettyPrinted error:nil];
The first part of your JSON, properly indented, is:
{
"source":"point a ",
"destination":"point b ",
"boardingPoint":{
"id":"2222",
"location":"Some location",
},
"customerName":"test",
"customerLastName":"testing",
"customerEmail":"test#gmail.com",
"blockSeatPaxDetails":[
{
"age":"20",
"name":"test123",
"sex":"M",
"title":"Mr",
"email":"testing#gmail.com",
},
(You've apparently elided something toward the end so I can't slow the last few lines.)
There is no "missing key" or anything of the sort. If you feed your (unelided) JSON through NSJSONSerialization it will produce the correct "tree" of dictionaries and arrays.

Converting NSData (Json data) to nsarray : iOS

I am getting some data from WebService (which is a json data)
Exact input sent by Webservice is:
[
{
"id": "C-62",
"title": "testing testing",
"type": "image",
"thumb": "",
"LinkId": "ABC",
"fileSize":1074,
"level":0,
},
{
"id": "C-63",
"title": "testing ab testing",
"type": "audio",
"thumb": "",
"LinkId": "ABCD",
"fileSize":1074,
"level":1,
}
]
As I can see in input data that only fileSize is a integer type Key-Value pair
remaining all are in string format.
When I convert that NSData onto NSArray using following code
NSArray *dataArray = nil;
dataArray = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
I get "dataArray" like this
{
"id": "C-62",
"title": "testing testing",
"type": image,
"thumb": "",
"LinkId": "ABC",
"fileSize":1074,
"level":0,
},
{
"id": "C-63",
"title": "testing ab testing",
"type": audio,
"thumb": "",
"LinkId": "ABCD",
"fileSize":1074,
"level":1,
}
The "type" Key-Value pair changes to "int" .All other key-value pairs are in same state.
Please help me in order to convert the input data into the same format as sent by web service.
I am using iOS 7.
You just got yourself confused. You confuse NSLog output with what is really stored. You are also not saying the truth when you claim that only the "fileSize" field contains numbers, because clearly the "level" field does as well.
NSLog only shows strings with quotes when necessary. A string "10" would be displayed as 10 without the quotes. You can really rely on NSJSONSerializer not doing anything behind your back.
NSJSONSerialization will convert scalar numbers to NSNumbers. That's the only way these can participate in collections (arrays and dictionaries). To convert to int, access the NSNumber and convert it as follows...
NSArray *dataArray = // the de-serialized json
NSDictionary *dictionary = dataArray[0]; // the first dictionary
NSNumber *number = dictionary[#"fileSize"];
// turn an NSNumber representing an integer to a plain int
int fileSizeInt = [number intValue];
But don't try to reinsert that int back into the dictionary.
The one tricky thing about JSON on iOS is figuring out the data type of an arbitrary NSNumber. I chronicled my difficulties in this question.
A large number might be floating-point or integer, and if you attempt to extract one when you really have the other you lose significant digits. And, obviously (in retrospect), if you extract a too-large value into an int you will lose high-order bits and get totally wrong values.
(This isn't quite so difficult if you know in advance that certain values are of certain types. Then it's just a matter of using the proper "verb" to extract the expected type of value.)

how to get JSON object from server as it (in the same order) iPhone

Is there any way to get JSON object from the server in the same order??
For example when i fitch using browser my JSON object return like this:
{
"23": {
"numberOfRecords": "3",
"startDate": "27/11/2013",
"endDate": "31/12/2014",
"question": "How do you rate the new MenaME Portal ?",
"voteScale": "5",
"questions": {
"option1": {
"value": "1",
"option": "Poor",
"voteResult": "50.000"
},
"option2": {
"value": "2",
"option": "Acceptable",
"voteResult": "0.000"
},
"option3": {
"value": "3",
"option": "Good",
"voteResult": "0.000"
},
"option4": {
"value": "4",
"option": "Very Good",
"voteResult": "0.000"
},
"option5": {
"value": "5",
"option": "Excellent",
"voteResult": "50.000"
}
},
"selectedAnswer": "0",
"voteAnswered": "0",
"votes": "6"
}
}
after parsing it with [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error]
the object returned like this :
{
23 = {
endDate = "31/12/2014";
numberOfRecords = 3;
question = "How do you rate the new MenaME Portal ?";
questions = {
option1 = {
option = Poor;
value = 1;
voteResult = "50.000";
};
option2 = {
option = Acceptable;
value = 2;
voteResult = "0.000";
};
option3 = {
option = Good;
value = 3;
voteResult = "0.000";
};
option4 = {
option = "Very Good";
value = 4;
voteResult = "0.000";
};
option5 = {
option = Excellent;
value = 5;
voteResult = "50.000";
};
};
selectedAnswer = 0;
startDate = "27/11/2013";
voteAnswered = 0;
voteScale = 5;
votes = 6;
};
}
Is there any way or framework to get the object as it (in the same order returned from the server) ??
Dictionaries, both in JSON and NSDictionary, are unordered, meaning that it is irrelevant which order you see things in the log. This is defined in the JSON specification and the documentation for NSDictionary.
If it actually matters what order things are displayed in, then either the API you are linking to isn't using correct JSON, or you're doing something wrong in your app. To help with those situations you can use several of the sorted NSDictionary implementations that are around.
Can I ask why you want to ensure the dictionary is maintained in the correct order?
I understand in some cases (mine) an ancient JSON -> XML web service was being called by my app and the client refused to adjust the service so it could accept unordered JSON (valid json) but if you're writing the app, why do you need to ensure that it is in order?
I have a NSMutableDictionary subclass that keeps objects added by setObject:forKey in the order you call the method that can be found here.
It works by storing a NSMutableOrderedSet of keys within the dictionary and then overrides the keyEnumerator method to return an enumerator based on the ordered set
- (NSEnumerator *)keyEnumerator
{
return [self.orderedSetOfKeys objectEnumerator];
}
You could modify the NSMutableDictionary subclass i created to expose the NSMutableOrderedSet in the public header and then modify this set yourself to get an ordered version of your dictionary.. For example:
NSDictionary *JSONWebServiceDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
LNOrderedMutableDictionary *orderedDictionary = [[LNOrderedMutableDictionary alloc] initWithDictionary:JSONWebServiceDictionary];
NSMutableOrderedSet *order = [[NSMutableOrderedSet alloc] initWithArray:#[#"key1",#"key2",#"key3"]]; //All the keys you are expecting and the order you want them in..
orderedDictionary.orderSet = order; //orderSet does not exist.. it is currently called `array` and not exposed in LNOrderedMutableDictionary.h
I haven't tested the code above but unless you want to create or modify an existing JSON parser then it seems that it is your only option..
If you did want to modify an existing parser then it might just be as simple as replacing dictionary instances with LNOrderedMutableDictionary to keep everything in order.
Another idea to expand the above sample code could be to replace
NSMutableOrderedSet *order = [[NSMutableOrderedSet alloc] initWithArray:#[#"key1",#"key2",#"key3"]];
with an array returned in the JSONWebServiceDictionary dictionary as arrays keep their order when parsed from JSON so maybe you could do this?
NSMutableOrderedSet *order = [[NSMutableOrderedSet alloc] initWithArray:[JSONWebServiceDictionary objectForKey:#"keyOrderArray"]]];
Look at what you have. If you test the result you got back from JSONObjectWithData (which we'll assume was declared as id jsonObject)
if ([jsonObject isKindOfClass:[NSDictionary class]) { ...
or
NSLog(#"The object type is %#", [jsonObject class]);
you will find that it is indeed an NSDictionary (or perhaps an NSMutableDictionary). That dictionary, as you can see from the dump (or infer from the nearly identical JSON) contains a single entry with a key of "23".
So let's cast the jsonObject to an NSDictionary and reference it:
NSDictionary* jsonDict = (NSDictionary*) jsonObject;
NSDictionary* entry23Dict = [jsonDict objectForKey:#"23"];
Now, if you NSLog entry23Dict you will discover it contains all of the above, absent the { 23 = ... } outermost dictionary.
You can then access, say, "questions" with
NSDictionary* questDict = [entry23Dict objectForKey:#"questions"];
From there the individual "option1", "option2", ... "option5" dictionaries can be accessed in a similar fashion. You simply proceed one layer at a time -- don't get overwhelmed by the entire structure. (It's often helpful, when you're first learning, to NSLog each "layer" as you "peel" it out of the containing structure.)
And, of course, you have all the standard facilities that are available to NSDictionary objects (and NSArray objects, should your JSON contain any [..] arrays). For instance, you can iterate on the keys of the dictionary with
for (NSString* key in jsonDict) {
NSLog(#"This entry's number is %#", key); // For the above will print "23"
NSDictionary* numberedDict = jsonDict[key]; // Using the "new" form of dictionary access
NSString* endDate = numberedDict[#"endDate"]; // Ditto
NSLog(#"The end date is %#", endDate);
}
This is a fairly common problem. It's also probably the most annoying part about iOS. (java doesn't have this issue at all). If you want to get back objects, take a look at restkit.org Specifically this answer may help: https://stackoverflow.com/a/8284343/836450

Resources