将Objective-C对象序列化和反序列化为JSON

时间:2011-08-24 07:37:27

标签: objective-c json couchdb nsarray nsdictionary

我需要将objective-c对象序列化和反序列化为JSON以存储在CouchDB中。人们是否有任何示例代码用于一般解决方案的最佳实践?我查看了一些JSON框架,它们在NSDictionary / NSArray级别停止。即很多框架会将NSDictionary / NSArray序列化和反序列化为JSON。但我仍然需要将NSDictionary转换为Objective-C对象。

为了使事情变得更复杂,我的对象A可以引用对象B的NSArray / NSDictionary。

我的问题与此问题非常相似,并且增加了收集要求。

Instantiating Custom Class from NSDictionary

7 个答案:

答案 0 :(得分:35)

最后,我们可以使用JSONModel轻松解决此问题。这是目前为止最好的方法。 JSONModel是一个基于Class一般序列化/反序列化对象的库。您甚至可以使用非基于nsobject的属性,例如intshortfloat。它还可以满足嵌套复杂的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]);

这是来自Serialize示例的NSLog结果:

{ "accounting" : [{ "firstName" : "Uee",  
                    "lastName"  : "Bae",
                    "age"       : 22 }
                 ],                            
  "sales"      : [{ "firstName" : "Sara", 
                    "lastName"  : "Jung",
                    "age"       : 20 }
                  ]}

答案 1 :(得分:10)

听起来您正在寻找一个序列化库,它可以让您将自己的自定义类的对象转换为JSON,然后重新构建它们。属性列表类型的序列化(NSArray,NSNumber等)已存在于第三方库中,甚至内置于OS X 10.7和iOS 5中。

所以,我认为答案基本上是“不”。我在一个或两个月之前在cocoa-dev邮件列表上问过这个确切的问题,而我最接近的是来自Mike Abdullah,他指着他写的一个实验性图书馆:

https://github.com/mikeabdullah/KSPropertyListEncoder

这会将对象归档到内存中的属性列表,但正如我所说,已有用于将这些对象转换为JSON的API。

还有一款名为Objectify的商业应用声称可以做类似的事情:

http://tigerbears.com/objectify/

我可能会最终实现你所要求的作为我的CouchCocoa库的一部分,但我还没有潜入这项任务。

https://github.com/couchbaselabs/CouchCocoa

答案 2 :(得分:7)

借助 NSDictionary,NSArray和NSJSONSerialization

,您可以轻松地将JSON功能添加到NSObject类中

序列化:

只要看一下这个例子就很容易理解。

将JSON功能添加到NSObject类: -

@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,然后将其分配给类属性。

我确信使用上面使用的方法和想法可以序列化&amp;轻松地对复杂的json进行反序列化。

答案 3 :(得分:4)

您可以尝试JTObjectMapping。他们的描述:

  

JTObjectMapping - 受RestKit的启发。一个非常简单的objective-c框架,它将来自NSDictionary或NSArray的JSON响应映射到iOS的NSObject子类。

它非常小(与RestKit不同)并且效果很好。

答案 4 :(得分:2)

使用RestKit库的对象映射系统可以实现这一点。

http://restkit.org/

答案 5 :(得分:2)

我有一个简单的模型类,我想把它变成一个JSON-Object。

为此,我在模型类中添加了一个“jsonData”方法: 该方法将模型属性转换为基础对象(int数字转换为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;

}

答案 6 :(得分:1)