KamyFC
KamyFC

Reputation: 898

Objective C - NSDictionary parsing nested JSON

Here is a deeply nested JSON that i'm trying to parse and create into model Objects.

Basically i need to create model objects until the 'Child' array has 0 elements.

enter image description here

This is what am doing

        dictTree = [dict[@"jsonTree"] mutableCopy];
        NSMutableArray *children = [[NSMutableArray alloc] init];
        if (dictTree.count > 0)
        {
            while (true)
            {
                CategoryChild *categoryChild = [[CategoryChild alloc]init];
                NSString *str = dictTree[@"id"];
                categoryChild.childId = str;
                categoryChild.name = dictTree[@"name"];
                categoryChild.type = dictTree[@"type"];
                categoryChild.parent = dictTree[@"parent"];
                categoryChild.symbol = dictTree[@"symbol"];
                categoryChild.multiple = dictTree[@"multiple"];
                categoryChild.metricUnit = dictTree[@"metricUnit"];

                [children addObject:categoryChild];
                dictTree = [dictTree[@"child"] mutableCopy];

                if (dictTree.count == 0)
                {
                    break;
                }
            }

            categoryItem.children = children;
            [categoryList addObject:categoryItem];
        }

Unfortunately during the second iteration when i access dictTree[@"id"] - get a crash

'NSInvalidArgumentException', reason: '-[__NSArrayM objectForKeyedSubscript:]: unrecognized selector sent to instance

The issue seems to be the fact that am assigning a dictionary to the 'child' dictionary and it does seem to like it.

Although in the debugger, i can see the child values.

enter image description here

Any ideas on how to go bout things or what am doing wrong would be appreciated. thank you.

Upvotes: 0

Views: 1306

Answers (2)

Amset
Amset

Reputation: 86

It seems like your children consists of arrays filled with one dictionary. You need to access the first object of this array to get the dictionary.

[children addObject:categoryChild];
if ([dictTree[@"child"] count] > 0) {
    dictTree = [dictTree[@"child"][0] mutableCopy];
}

enter image description here

The debugger also shows that dictTree consists of one element at key 0. That element is your dictionary.

Upvotes: 0

Sandeep Bhandari
Sandeep Bhandari

Reputation: 20379

Change

dictTree = [dict[@"jsonTree"] mutableCopy];

to

 dictTree = [dict[@"jsonTree"][@"child"] mutableCopy];

That should do the job.

Value for key jsonTree is a jSON and not JSONArray as you are expecting. JSONArray is the value for key "child" inside "jsonTree".

I hope you are aware of the fact that your code will not be able to parse the second child object if present in JSONArray. Looking at your jSON where there is only one JSON per child key code looks fine. But in case if there is more than one jSON per key "child" you need a better code to parse.

EDIT:

A little cleaner approach I can think of

- (void) parseChildrenArray : (NSArray *) dict {
    for(NSDictionary *child in dict) {
        CategoryChild *createdChild = [self createCategory:child];
        [self.childrenArray addObject:createdChild];
        if ([child[@"child"] count] > 0) {
            [self parseChildrenArray:child[@"child"]];
        }
    }
}

-(CategoryChild *)createCategory: (NSDictionary *)child {
    CategoryChild *ch = [[CategoryChild alloc] init];
    ch.id = child[@"id"];
    //parse other property
    return ch;
}

Declare a property

@property (nonatomic,strong) NSMutableArray *childrenArray;

Finally call

NSDictionary *tree = json[@"jsonTree"];
self.childrenArray = [[NSMutableArray alloc] init];
[self parseChildrenArray:tree[@"child"]];

Upvotes: 1

Related Questions