使用NSKeyValueCoding将复杂的JSON API响应消耗到NSObject中

时间:2012-09-10 15:02:22

标签: iphone ios json nsobject key-value-coding

博文SAVING JSON TO CORE DATA提供了一些将JSON响应转换为核心数据实体的重要提示。我想要做的是更具体一点。我想采用JSON响应并使用博客文章中的方法将对象转换为具有表示响应对象的属性的NSObject。我遇到的问题是对象的嵌套属性。以此JSON响应为例:

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

使用博客文章中描述的方法,简单的属性,如" name"和"等级"很容易转换为NSString和NSNumber对象。但是,当查看响应的更复杂部分时会出现问题:嵌套数组/字典。

我发现的唯一解决方案是手工编码所有这些属性的发现和转换,我认为这是一种非常糟糕的做法。这是我正在做的事情的摘录:

    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;
    }

2 个答案:

答案 0 :(得分:3)

我使用SBJSON库和ASIHttpRequest从我自己设计的web服务中获取和使用JSON,如果我正确理解你的问题,你只需要做这样的事情:

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

SBJSON库将为你进行转换到NSObjects并使用key:value编码JSON元素将它们放入Arrays / Dictionaries中,所以使用你提供的JSON我可以得到第一个英雄的名称:

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

SBJson可以在这里找到:http://stig.github.com/json-framework/

答案 1 :(得分:0)

BWJSONMatcher是一个轻量级库,我在我的项目中用于将RESTful api中的JSON数据转换为我的业务数据模型。它是这样的:

...
NSString *jsonString = @"{your-json-string}";
YourValueObject *dataModel = [YourValueObject fromJSONString:jsonString];

NSDictionary *jsonObject = @{your-json-object};
YourValueObject *dataModel = [YourValueObject fromJSONObject:jsonObject];
...
YourValueObject *dataModel = instance-of-your-value-object;
NSString *jsonString = [dataModel toJSONString];
NSDictionary *jsonObject = [dataModel toJSONObject];
...