如何在Objective-C中将JSON结构转换为对象?

时间:2012-02-03 17:56:43

标签: objective-c json

我有一个像这样的JSON结构:

{
  id:100
  contactInfo: {
    name: John Doe
    city: New York
  }
}

以及具有以下属性的相应Customer类,包括嵌套的contactInfo类。

Customer.id
Customer.contactInfo.name
Customer.contactInfo.city

是否可以将JSON数据直接转换为Customer类的实例?

我知道如何获取NSDictionary对象,但这非常麻烦且使用起来很冗长,而是希望将数据直接转换/反序列化到Customer类。

已获编辑附加信息:

在我使用过的其他语言中,内置支持将JSON反序列化为自定义对象。您所要做的就是将类标记为“Serializable”,并且无需在每个类中编写自定义代码即可反序列化JSON。

如果类具有嵌套类,则NSDictionary对象可能变得非常麻烦。使用像这样的自定义对象属性会更容易

Customer.contactInfo.name

而不是

[(NSDictionary*)[customerDict objectForKey:@"contactInfo"] objectForKey:@"name"]

因此我的问题是关于Objective-C中的标准内置反序列化器。

6 个答案:

答案 0 :(得分:1)

我不知道为什么你认为这很麻烦。一种简单的方法是为客户对象创建一个初始化者,将字典作为参数。

通过这种方式,您可以将下载的数据作为JSON,将其反序列化为字典,然后将其传递给初始化程序,以便从字典中创建对象。

答案 1 :(得分:1)

许多JSON库中的任何一个都将解析您的JSON字符串并将其转换为NSDictionary。如果您不想自己编写解析器,则必须处理中间格式。但是,一旦拥有了NSDictionary,就可以使用键值编码(KVC)来设置对象的属性:

for (NSString *key in jsonDictionary) {
    [customer setValue:[jsonDictionary objectForKey] forKey:key];
}

KVC内置于Cocoa中,并为所有对象定义setValue:forKey:,因此您可以按名称设置属性,无论它们是如何定义的。

你必须做一些比上面循环更聪明的事情来处理你的内部ContactInfo类,但是你应该能够解决这个问题。为了安全起见(因为JSON可能来自网络),您可能希望制作密钥的白名单并循环使用,并使用valueForKeyPath: / setValue:forKeyPath:来处理嵌套对象。

答案 2 :(得分:1)

答案 3 :(得分:0)

考虑使用RestKit api(http://restkit.org/)及其对象映射系统......

以下是一些维基:https://github.com/RestKit/RestKit/wiki/Object-mapping

答案 4 :(得分:0)

为Customer类编写一个初始化程序,它将JSON数据作为参数,如:

-(id)initWithJSONData:(NSData*)data;

您可以实现该方法来执行Abizern建议的操作:将数据读入字典,然后从字典中提取所需的任何值。

如果你想获得想象力,另一种方法是在你的Customer类中采用NSCoding,然后创建一个反序列化JSON数据的NSCoder子类。这可能非常像NSKeyedUnarchiver。看起来似乎并不值得,除非你打算采用与你的一些课程相同的方法。

答案 5 :(得分:0)

使用此library,您可以执行以下操作:

SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *customer = [parser objectWithString:jsonString];

然后,您可以使用以下方式访问您的媒体资源:

[customer objectForKey:@"id"];
[[customer objectForKey:@"contactInfo"] objectForKey:@"name"];
[[customer objectForKey:@"contactInfo"] objectForKey:@"city"];

然后,您可以在Customer类的init函数中使用此代码。例如:

- (id)initWithJSON:(NSString *)jsonString {
    self = [super init]; // or whatever you need here
    if (self) {
        SBJSON *parser = [[SBJSON alloc] init];
        NSDictionary *customer = [parser objectWithString:jsonString];

        self.id = [customer objectForKey:@"id"];
        self.contactInfo = [[NSDictionary alloc] initWithObjectsAndKeys:[[customer objectforKey:@"contactInfo"] objectForKey:@"name"], @"name", [[customer objectforKey:@"contactInfo"] objectForKey:@"city"], @"city"]
    }
    return self;
}