Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to parse json array returned by a restful web APS for an iOS project

I am trying to parse a JSON array returned by a RESTful web API that looks similiar to the following (using jsonviewer the json is returned as a bunch of dictionaries in an array):

[{
"date": "2011-03-21",
"meal": "BREAKFAST",
"category": "BREAKFAST BAKERY",
"recipe": "213012",
"name": "Aesops Bagels",
"portion": "1",
"unit": "each"},

I am trying to get the "name" information and then store it into an tableview. Here is the code I am using to accomplish that:

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSArray *allDataArray = [NSJSONSerialization JSONObjectWithData:webData 
                                                            options:0 
                                                              error:nil];

    for (NSDictionary *diction in allDataArray) {
        NSDictionary *menuItem = [diction objectForKey:@"menuItem"];
        NSString *name = [menuItem objectForKey:@"name"];

        [array addObject:name];
    }

    [[self MyTableView]reloadData];
}

The error that I am getting is:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

So I'm pretty sure that there is an error occurring in the line above the for loop, and this is causing the array to try to take nil as a value. But any help figuring out what is going wrong/how to successfully parse this json would be extremely appreciated. I am very new to both json, xcode, and iOS so I apologize if I have done anything particularly stupid.

like image 567
Andrew Schutts Avatar asked Dec 01 '12 08:12

Andrew Schutts


2 Answers

You don't actually have an item called menuItem in your JSON sample. Your code looks as it was written to parse JSON that looks like this:

[{ "menuItem" : { "name" : "Aesops Bagels",
                  …
                }
 },
]

ie, its expecting a "menuItem" key in each dictionary in the list. If you're actually trying to parse the snippet you posted, I think you just need to simplify your loop code from this:

NSDictionary *menuItem = [diction objectForKey:@"menuItem"];
NSString *name = [menuItem objectForKey:@"name"];

to:

NSString *name = [diction objectForKey:@"name"];

You may also want to make sure that name isn't nil before you attempt to add it to your results array, just in case your data has an entry that's missing a name.

like image 159
ckhan Avatar answered Oct 04 '22 21:10

ckhan


As ckhan said, your JSON object is just an array of dictionaries, without any reference to "menuitem". If in fact you don't have a "menuitem" entry in your JSON object (i.e. assuming the JSON provided in your question is representative), then it would simply be:

for (NSDictionary *diction in allDataArray)
    [array addObject:[diction objectForKey:@"name"]];

Or

[allDataArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    [array addObject:obj[@"name"]];
}];

Or, more simply, make array an immutable NSArray rather than a NSMutableArray and use the following:

NSArray *array = [allDataArray valueForKey:@"name"];

By the way, if you're really concerned that some of the dictionary entries might not have the "name" entry, while the one line valueForKey handles that, the others would need to add the conditional logic, e.g.:

for (NSDictionary *diction in allDataArray) {
    id value = diction[@"name"];
    if (value == nil)
        value = [NSNull null];
    [array addObject:value];
};

Clearly, I'm adding a NSNull to the array so that you know that there was a dictionary entry for which there was no name. How you want to handle this scenario (e.g., add a NSNull, simply add nothing, etc.) is up to you, but hopefully this gives you the idea. But I think the main problem was the "menuitem" reference, so this may be moot.

like image 44
Rob Avatar answered Oct 04 '22 21:10

Rob