Cocoa:将json字符串反序列化为自定义对象(不是NSDictionary,NSArray)

时间:2021-10-05 21:21:03

In java-land, there are a handful of useful libraries which will convert json strings to objects of matching type. The json libraries I've seen for cocoa simply create nested NSDictionaries and NSArrays. Is there a tool out there which will go the extra step of reconstituting whatever object type I want?

在java-land中,有一些有用的库可以将json字符串转换为匹配类型的对象。我见过的可可的json库只是创建了嵌套的NSDictionaries和NSArrays。有没有一个工具可以重新构建我想要的任何对象类型的额外步骤?

So, for example, if I have a class called "Unicorn", with a property "maneColor", and I have json that looks like this:

所以,例如,如果我有一个名为“Unicorn”的类,其属性为“maneColor”,我的json看起来像这样:

{
 "maneColor":"silver"
}

I can automatically instantiate a Unicorn object with "maneColor" set to "silver".

我可以自动实例化“maneColor”设置为“silver”的Unicorn对象。

4 个解决方案

#1


7  

I'm not aware of any specific implementations, but key-value coding gets you very close to what you want: Key Value Coding Guide. I've had good results combining streamed json parsing with KVC.

我不知道任何具体的实现,但键值编码可以让您非常接近您想要的:键值编码指南。结合流式json解析和KVC,我有很好的结果。

The -setValue:forKey: method makes adapting serialized data to custom objects fairly straightforward. To continue with your example, you'd create a Unicorn class with all required accessor methods: -setName:/-name, -setManeColor/-maneColor, etc. (You may be able to use properties for some expected values, but there are cases, as with the maneColor value, where you probably want to write a custom setter to convert from the color name string to an NSColor or UIColor object.)

-setValue:forKey:方法使序列化数据适应自定义对象相当简单。要继续您的示例,您将创建一个包含所有必需访问器方法的Unicorn类:-setName:/ - name,-setManeColor / -maneColor等。(您可以使用某些预期值的属性,但有例如,与maneColor值一样,您可能希望编写自定义setter以将颜色名称字符串转换为NSColor或UIColor对象。)

You'll also want to add two more methods to your custom object: -setValue:forUndefinedKey: and -valueForUndefinedKey:. These are the methods that will be called if your object has no accessor methods matching a key passed into the KVC methods. You can catch unexpected or unsupported values here, and store them or ignore them as necessary.

您还需要向自定义对象添加两个方法:-setValue:forUndefinedKey:和-valueForUndefinedKey:。如果您的对象没有与传递给KVC方法的键匹配的访问器方法,则会调用这些方法。您可以在此处捕获意外或不受支持的值,并根据需要存储或忽略它们。

When you send -setValue:forKey: to the Unicorn object, the framework looks for accessors matching the key pattern. For instance, if the key is "maneColor" and you're setting the value, the framework checks to see if your object implements -setManeColor:. If so, it invokes that method, passing in the value; otherwise, -setValue:forUndefinedKey: is called, and if your object doesn't implement it, an exception is thrown.

将-setValue:forKey发送到Unicorn对象时,框架会查找与键模式匹配的访问器。例如,如果键是“maneColor”并且您正在设置值,则框架将检查您的对象是否实现了-setManeColor:。如果是这样,它会调用该方法,传入值;否则,调用-setValue:forUndefinedKey:如果您的对象没有实现它,则抛出异常。

When your parser's delegate receives notification that parsing a json unicorn object has begun, instantiate a Unicorn object. As your parser returns the parsed data to you, use -setValue:forKey: to add the data to your object:

当解析器的委托收到解析json unicorn对象的通知时,实例化一个Unicorn对象。当您的解析器将解析后的数据返回给您时,请使用-setValue:forKey:将数据添加到您的对象:

- ( void )parserDidBeginParsingDictionary: (SomeParser *)p
{
     self.currentUnicorn = [ Unicorn unicorn ];
}

- ( void )parser: (SomeParser *)p didParseString: (NSString *)string
          forKey: (NSString *)key
{
    [ self.currentUnicorn setValue: string forKey: key ]
}

- ( void )parserDidFinishParsingDictionary: (SomeParser *)p
{
    [ self.unicorns addObject: self.currentUnicorn ];
}

#2


7  

Use Jastor - https://github.com/elado/jastor Takes already parsed JSON into NSDictionary and fills an instance of real Objective-C class.

使用Jastor - https://github.com/elado/jastor将已经解析的JSON解析为NSDictionary并填充真实Objective-C类的实例。

NSDictionary *parsedJSON = (yajl, JSONKit etc)
Unicorn *unicorn = [[Unicorn alloc] initWithDictionary:parsedJSON];

unicorn.maneColor // "silver"

#3


1  

As any subclass of NSObject conforms to NSKeyValueCoding protocol:

由于NSObject的任何子类符合NSKeyValueCoding协议:

NSDictionary *parsedJSON = //whatever
id <NSKeyValueCoding> entity = [[CustomNSObjectSubclass alloc] init];
[entity setValuesForKeysWithDictionary:parsedJSON];

#4


0  

Apple added the NSJSONSerialization class to iOS 5.0 which, according to the documentation, does the following:

Apple将NSJSONSerialization类添加到iOS 5.0,根据文档,它执行以下操作:

You use the NSJSONSerialization class to convert JSON to Foundation objects and convert Foundation objects to JSON.

您使用NSJSONSerialization类将JSON转换为Foundation对象并将Foundation对象转换为JSON。

An object that may be converted to JSON must have the following properties:

可以转换为JSON的对象必须具有以下属性:

The top level object is an NSArray or NSDictionary. All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull. All dictionary keys are instances of NSString. Numbers are not NaN or infinity.

*对象是NSArray或NSDictionary。所有对象都是NSString,NSNumber,NSArray,NSDictionary或NSNull的实例。所有字典键都是NSString的实例。数字不是NaN或无穷大。

Here's a tutorial and wrapper method to get you started.

这是一个帮助您入门的教程和包装器方法。

#1


7  

I'm not aware of any specific implementations, but key-value coding gets you very close to what you want: Key Value Coding Guide. I've had good results combining streamed json parsing with KVC.

我不知道任何具体的实现,但键值编码可以让您非常接近您想要的:键值编码指南。结合流式json解析和KVC,我有很好的结果。

The -setValue:forKey: method makes adapting serialized data to custom objects fairly straightforward. To continue with your example, you'd create a Unicorn class with all required accessor methods: -setName:/-name, -setManeColor/-maneColor, etc. (You may be able to use properties for some expected values, but there are cases, as with the maneColor value, where you probably want to write a custom setter to convert from the color name string to an NSColor or UIColor object.)

-setValue:forKey:方法使序列化数据适应自定义对象相当简单。要继续您的示例,您将创建一个包含所有必需访问器方法的Unicorn类:-setName:/ - name,-setManeColor / -maneColor等。(您可以使用某些预期值的属性,但有例如,与maneColor值一样,您可能希望编写自定义setter以将颜色名称字符串转换为NSColor或UIColor对象。)

You'll also want to add two more methods to your custom object: -setValue:forUndefinedKey: and -valueForUndefinedKey:. These are the methods that will be called if your object has no accessor methods matching a key passed into the KVC methods. You can catch unexpected or unsupported values here, and store them or ignore them as necessary.

您还需要向自定义对象添加两个方法:-setValue:forUndefinedKey:和-valueForUndefinedKey:。如果您的对象没有与传递给KVC方法的键匹配的访问器方法,则会调用这些方法。您可以在此处捕获意外或不受支持的值,并根据需要存储或忽略它们。

When you send -setValue:forKey: to the Unicorn object, the framework looks for accessors matching the key pattern. For instance, if the key is "maneColor" and you're setting the value, the framework checks to see if your object implements -setManeColor:. If so, it invokes that method, passing in the value; otherwise, -setValue:forUndefinedKey: is called, and if your object doesn't implement it, an exception is thrown.

将-setValue:forKey发送到Unicorn对象时,框架会查找与键模式匹配的访问器。例如,如果键是“maneColor”并且您正在设置值,则框架将检查您的对象是否实现了-setManeColor:。如果是这样,它会调用该方法,传入值;否则,调用-setValue:forUndefinedKey:如果您的对象没有实现它,则抛出异常。

When your parser's delegate receives notification that parsing a json unicorn object has begun, instantiate a Unicorn object. As your parser returns the parsed data to you, use -setValue:forKey: to add the data to your object:

当解析器的委托收到解析json unicorn对象的通知时,实例化一个Unicorn对象。当您的解析器将解析后的数据返回给您时,请使用-setValue:forKey:将数据添加到您的对象:

- ( void )parserDidBeginParsingDictionary: (SomeParser *)p
{
     self.currentUnicorn = [ Unicorn unicorn ];
}

- ( void )parser: (SomeParser *)p didParseString: (NSString *)string
          forKey: (NSString *)key
{
    [ self.currentUnicorn setValue: string forKey: key ]
}

- ( void )parserDidFinishParsingDictionary: (SomeParser *)p
{
    [ self.unicorns addObject: self.currentUnicorn ];
}

#2


7  

Use Jastor - https://github.com/elado/jastor Takes already parsed JSON into NSDictionary and fills an instance of real Objective-C class.

使用Jastor - https://github.com/elado/jastor将已经解析的JSON解析为NSDictionary并填充真实Objective-C类的实例。

NSDictionary *parsedJSON = (yajl, JSONKit etc)
Unicorn *unicorn = [[Unicorn alloc] initWithDictionary:parsedJSON];

unicorn.maneColor // "silver"

#3


1  

As any subclass of NSObject conforms to NSKeyValueCoding protocol:

由于NSObject的任何子类符合NSKeyValueCoding协议:

NSDictionary *parsedJSON = //whatever
id <NSKeyValueCoding> entity = [[CustomNSObjectSubclass alloc] init];
[entity setValuesForKeysWithDictionary:parsedJSON];

#4


0  

Apple added the NSJSONSerialization class to iOS 5.0 which, according to the documentation, does the following:

Apple将NSJSONSerialization类添加到iOS 5.0,根据文档,它执行以下操作:

You use the NSJSONSerialization class to convert JSON to Foundation objects and convert Foundation objects to JSON.

您使用NSJSONSerialization类将JSON转换为Foundation对象并将Foundation对象转换为JSON。

An object that may be converted to JSON must have the following properties:

可以转换为JSON的对象必须具有以下属性:

The top level object is an NSArray or NSDictionary. All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull. All dictionary keys are instances of NSString. Numbers are not NaN or infinity.

*对象是NSArray或NSDictionary。所有对象都是NSString,NSNumber,NSArray,NSDictionary或NSNull的实例。所有字典键都是NSString的实例。数字不是NaN或无穷大。

Here's a tutorial and wrapper method to get you started.

这是一个帮助您入门的教程和包装器方法。