Consuming complex JSON API responses into NSObjects using NSKeyValueCoding

The blog post SAVING JSON TO CORE DATA has some great tips for converting a JSON response into a Core Data entity. What I want to do is a little bit more specific. I'd like to take a JSON response and convert the objects using the methods in the blog post into an NSObject with properties representing the response objects. The problem that I'm running into are nested properties of the object. Take this JSON response as an example:

http://us.battle.net/api/d3/profile/rnystrom-1254/

Using the methods described in the blog post, simple properties like "name" and "level" are easy to convert to NSString and NSNumber objects. However the problem arises when looking at more complex parts of the response: nested arrays/dictionaries.

The only solution I've found is to hand-code the finding and converting of all of these properties which I feel is a really poor practice. Here's an excerpt of what I'm doing:

    NSDictionary *skillsDictionary = json[@"skills"];
    if ([skillsDictionary isKindOfClass:[NSDictionary class]]) {
        NSArray *activeArray = skillsDictionary[@"active"];
        NSArray *passiveArray = skillsDictionary[@"passive"];

        NSMutableArray *mutActives = [NSMutableArray array];
        NSMutableArray *mutPassives = [NSMutableArray array];

        if ([activeArray isKindOfClass:[NSArray class]]) {
            [activeArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                if ([obj isKindOfClass:[NSDictionary class]]) {
                    NSDictionary *activeJSON = (NSDictionary*)obj;
                    D3Skill *skill = [D3Skill activeSkillFromJSON:activeJSON];
                    if (skill) {
                        [mutActives addObject:skill];
                    }
                }
            }];
        }

        if ([passiveArray isKindOfClass:[NSArray class]]) {
            [passiveArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                if ([obj isKindOfClass:[NSDictionary class]]) {
                    NSDictionary *passiveJSON = (NSDictionary*)obj;
                    D3Skill *skill = [D3Skill passiveSkillFromJSON:passiveJSON];
                    if (skill) {
                        [mutPassives addObject:skill];
                    }
                }
            }];
        }

        self.activeSkills = mutActives;
        self.passiveSkills = mutPassives;
    }

Answers


I use the SBJSON library and ASIHttpRequest to fetch and consume JSONs from a webservice of my own design, if I understand your question correctly, you'd just need to do something like this:

NSString *responseJSONasString = [fetchRequest responseString]; 
NSDictionary *itemResponseArray = [responseJSONasString JSONValue];

The SBJSON library will do the converting for you into NSObjects and put them into Arrays/Dictionaries using key:value coding on the JSON elements, so with the JSON you provided I could get the first hero's name with:

NSArray *heroes = [itemResponseArray objectForKey:@"heroes"];
NSDictionary *firstHero = [heroes objectAtIndex:0];
NSString *heroName = [firstHero objectForKey:"name"];

SBJson can be found here: http://stig.github.com/json-framework/


Need Your Help

Comparing data between two MySQL tables with PHP

php mysql

I have two tables table1 = records, table2 = duplicates. Both tables contain a variable number of columns at any given time and they both contain the exact same columns with the exception of table2