将 Objective-C 对象序列化和反序列化为 JSON
Posted
技术标签:
【中文标题】将 Objective-C 对象序列化和反序列化为 JSON【英文标题】:Serialize and Deserialize Objective-C objects into JSON 【发布时间】:2011-08-24 07:37:27 【问题描述】:我需要将objective-c 对象序列化和反序列化为JSON 以存储在CouchDB 中。人们是否有任何示例代码可用于一般解决方案的最佳实践?我查看了一些 JSON 框架,它们停在 NSDictionary/NSArray 级别。即很多框架会将 NSDictionary/NSArray 序列化和反序列化为 JSON。但我仍然需要将 NSDictionary 转换为 Objective-C 对象。
为了让事情变得更复杂,我的对象 A 可以引用对象 B 的 NSArray/NSDictionary。
我的问题与这个问题非常相似,但增加了收集要求。
Instantiating Custom Class from NSDictionary
【问题讨论】:
现在是 2013 年,出于某种原因,似乎没有很好的答案。我看过的 RestKit 和其他框架似乎需要完成大量的“映射”,这是没有意义的。对象已经描述了自己。 Json 到 NSOBbjects 有哪些框架。我不在乎他们是否停在 NSArray 或 NSDictionary。 【参考方案1】:最后我们可以使用JSONModel轻松解决这个问题。这是迄今为止最好的方法。 JSONModel 是一个基于 Class 对对象进行一般序列化/反序列化的库。你甚至可以对int
、short
和float
等属性使用非nsobject。它还可以满足嵌套复杂的 JSON。
考虑这个 JSON 示例:
"accounting" : [ "firstName" : "John",
"lastName" : "Doe",
"age" : 23 ,
"firstName" : "Mary",
"lastName" : "Smith",
"age" : 32
],
"sales" : [ "firstName" : "Sally",
"lastName" : "Green",
"age" : 27 ,
"firstName" : "Jim",
"lastName" : "Galley",
"age" : 41
]
1) 反序列化示例。在头文件中:
#import "JSONModel.h"
@interface Person : JSONModel
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSNumber *age;
@end
@protocol Person;
@interface Department : JSONModel
@property (nonatomic, strong) NSMutableArray<Person> *accounting;
@property (nonatomic, strong) NSMutableArray<Person> *sales;
@end
在实现文件中:
#import "JSONModelLib.h"
#import "myJSONClass.h"
NSString *responseJSON = /*from example*/;
Department *department = [[Department alloc] initWithString:responseJSON error:&err];
if (!err)
for (Person *person in department.accounting)
NSLog(@"%@", person.firstName);
NSLog(@"%@", person.lastName);
NSLog(@"%@", person.age);
for (Person *person in department.sales)
NSLog(@"%@", person.firstName);
NSLog(@"%@", person.lastName);
NSLog(@"%@", person.age);
2) 序列化示例。在实现文件中:
#import "JSONModelLib.h"
#import "myJSONClass.h"
Department *department = [[Department alloc] init];
Person *personAcc1 = [[Person alloc] init];
personAcc1.firstName = @"Uee";
personAcc1.lastName = @"Bae";
personAcc1.age = [NSNumber numberWithInt:22];
[department.accounting addOject:personAcc1];
Person *personSales1 = [[Person alloc] init];
personSales1.firstName = @"Sara";
personSales1.lastName = @"Jung";
personSales1.age = [NSNumber numberWithInt:20];
[department.sales addOject:personSales1];
NSLog(@"%@", [department toJSONString]);
这是序列化示例的 NSLog 结果:
"accounting" : [ "firstName" : "Uee",
"lastName" : "Bae",
"age" : 22
],
"sales" : [ "firstName" : "Sara",
"lastName" : "Jung",
"age" : 20
]
【讨论】:
嗨!很好的例子,我尝试了同样的方法,但是当我添加对象 personSales1(在序列化示例中)时,department.sales 仍然为零。 Department.accounting 也是如此。我该如何解决?我必须在部门对象中初始化每个 NSMutableArray 吗?非常感谢! 我找到了自己的解决方案:我必须初始化 department.sales = [[NSMutableArray alloc] init];让它工作。这让我疯狂了很长时间! Department.accounting 也是如此。希望这对其他人有所帮助... 这是一个非常棒的库——但它对使用单引号和双引号的输入 JSON 是否严重敏感? 使用前需要对department.sales进行初始化和强制转换。 department.sales = (NSMutableArrayJSONModel
继承你所有的模型类,这一点都不好。这是我会避免的限制。【参考方案2】:
听起来您正在寻找一个序列化库,可以让您将自己的自定义类的对象转换为 JSON,然后将它们重新组合回来。属性列表类型(NSArray、NSNumber 等)的序列化已经存在于 3rd 方库中,甚至内置于 OS X 10.7 和 ios 5 中。
所以,我认为答案基本上是“不”。一两个月前,我在 cocoa-dev 邮件列表上问了这个确切的问题,我最接近成功的是 Mike Abdullah,他指着他写的一个实验库:
https://github.com/mikeabdullah/KSPropertyListEncoder
这会将对象存档到内存中的属性列表,但正如我所说,已经有 API 可以将它们转换为 JSON。
还有一个名为 Objectify 的商业应用,声称能够做类似的事情:
http://tigerbears.com/objectify/
我最终可能会在我的 CouchCocoa 库中实现您所要求的内容,但我还没有深入研究该任务。
https://github.com/couchbaselabs/CouchCocoa
【讨论】:
谢谢詹斯!期待您的图书馆!【参考方案3】:您可以在 NSDictionary、NSArray 和 NSJSONSerialization 的帮助下轻松地将 JSON 功能添加到 NSObject 类
序列化:
看例子就很容易理解了。
为 NSObject 类添加 JSON 功能:-
@interface JsonClassEmp : NSObject
@property(strong,nonatomic)NSString *EmpName,*EmpCode;
-(NSDictionary*)GetJsonDict;
@end
@implementation JsonClassEmp
@synthesize EmpName,EmpCode;
//Add all the properties of the class in it.
-(NSDictionary*)GetJsonDict
return [NSDictionary dictionaryWithObjectsAndKeys:EmpName,@"EmpName",EmpCode,@"EmpCode", nil];
@end
JSON 字符串生成器:-
在 iOS 5 中,Apple 引入了 NSJSONSerialization,用于解析 JSON 字符串,因此我们将生成 JSON 字符串。
-(NSString*)GetJSON:(id)object
NSError *writeError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object options:NSJSONWritingPrettyPrinted error:&writeError];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
return jsonString;
转向 Apple 的实施总是更安全,因为您可以保证它会得到维护并保持最新。
使用方法:-
- (void)viewDidLoad
[super viewDidLoad];
JsonClassEmp *emp1=[[JsonClassEmp alloc]init];
[emp1 setEmpName:@"Name1"];
[emp1 setEmpCode:@"1"];
JsonClassEmp *emp2=[[JsonClassEmp alloc]init];
[emp2 setEmpName:@"Name2"];
[emp2 setEmpCode:@"2"];
//Add the NSDictionaries of the instances in NSArray
NSArray *arrEmps_Json=@[emp1.GetJsonDict,emp2.GetJsonDict];
NSLog(@"JSON Output: %@", [self GetJSON:arrEmps_Json]);
Reference
反序列化:
这是将反序列化数据放入 NSDictionary 或 NSArray 然后将其分配给类属性的常用方法。
我确信使用上面使用的方法和想法,您可以轻松地序列化和反序列化复杂的 json。
【讨论】:
【参考方案4】:您可能想试试JTObjectMapping。他们的描述:
JTObjectMapping - 受 RestKit 启发。一个非常简单的objective-c 框架,将来自NSDictionary 或NSArray 的JSON 响应映射到iOS 的NSObject 子类。
它非常小(与 RestKit 不同)而且效果很好。
【讨论】:
谢谢泽克尔! JTObjectMapping 解耦了 Model 对象之外的映射,这允许您在任何 NSObject 子类中使用,并满足 API 端点与数据结构不一致的情况。我最近还为 CamelCases 添加了对下划线的支持,您永远不需要为此提供任何映射(例如 full_name -> fullName) @JamesTang JTObjectMapping 非常轻量级,但我无法让它与自定义对象的嵌套数组一起使用。【参考方案5】:这可以使用 RestKit 库的对象映射系统。
http://restkit.org/
【讨论】:
【参考方案6】:我有一个简单的模型类,我想把它变成一个 JSON 对象。
为此,我在模型类中添加了一个“jsonData”方法: 该方法将模型属性转换为基础对象(int numbers 转换为 NSNumber 对象等) 然后用这些对象和相应的键(也是后来的 JSON 键)填充字典。 在(可选)检查有效性之后,使用 NSJSONSerialization 创建 JSON 数据对象 类“dataWithJSONObject”方法并返回。
- (NSData *)jsonData
NSDictionary *root = @@"Sport" : @(_sportID), // I´m using literals here for brevity’s sake
@"Skill" : @(_skillLevel),
@"Visibility" : @(_visibility),
@"NotificationRange" : @(_notificationRange);
if ([NSJSONSerialization isValidJSONObject:root])
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:root
options:0
error:nil];
return jsonData;
return nil;
【讨论】:
【参考方案7】:你是这个意思吗? ;)
http://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40010946
【讨论】:
NSJSONSerialization 仅对基础对象进行序列化/反序列化,我认为所要求的是一种在应用程序数据模型中序列化/反序列化对象的方法。 RESTKit 会做到这一点,但如果你想要的只是它提供的映射,它是一个繁重的解决方案。以上是关于将 Objective-C 对象序列化和反序列化为 JSON的主要内容,如果未能解决你的问题,请参考以下文章