2013-02-19 44 views
9

任何人都知道如何序列化基于NSObject类的嵌套JSON?有一个讨论序列化简单的JSON here,但它不足以满足复杂的嵌套JSON。iOS:从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 } 
        ]} 

从这节课:

@interface Person : NSObject{} 
@property (nonatomic, strong) NSString *firstName; 
@property (nonatomic, strong) NSString *lastName; 
@property (nonatomic, strong) NSNumber *age; 
@end 

@interface Department : NSObject{} 
@property (nonatomic, strong) NSMutableArray *accounting; //contain Person class 
@property (nonatomic, strong) NSMutableArray *sales; //contain Person class 
@end 

/反序列化他们基于类一般如何序列化?

编辑

我目前能够产生有效载荷像这样基于任何类:

NSMutableDictionary *Payload = [self serialize:objClass]; 

但它并不满足嵌套复杂的JSON。任何人都有更好的解决方案? This library for C#cater基于对象类的serialize/deserialze。我想根据NSObject重现相同的东西

+0

其中一种方法不是 - 继续处理NSDictionary对象而不是自定义类。这通常比你想象的更好。 – 2014-01-08 13:12:49

+0

您可以随时向您的类'initWithJSONObject:error:'添加一个方法(例如,通过一个类别)。 – CouchDeveloper 2014-01-08 13:47:59

+0

@CouchDeveloper - 'initWithDictionary'可能更通用。 (你可以包含'error:'parm,如果它是合适的。) – 2014-01-08 16:49:44

回答

12

最后我们可以用JSONModel轻松解决这个问题。这是迄今为止最好的方法。 JSONModel是一个通用的基于Class序列化/反序列化对象的库。您甚至可以使用基于非,shortfloat之类的属性的非nsobject。它也可以提供嵌套复杂的JSON。

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 } 
        ]} 
+1

由于您知道模型将从json填充,因此可以包含一个'initWithDictionary:'方法,将映射保留到各个模型中。 – Anupdas 2013-06-05 10:08:31

+0

是的,'initWithDictionary'在这种情况下是一种很好的初始化方法,它的优点是它也可以用于响应“本地”需求而被引用的一般情况。尤其是使用新的@ {...}'表示法时,可以很容易地创建一个包含所有参数的字典(如果JSON不提供一个现成的)。此外,如果您使用JSONSerialization选项为您提供可变对象,则可以修改传入字典以例如更改键名,或者添加JSON中可能缺少的其他参数。 – 2014-01-08 16:48:04

+0

感谢您的解决方案,它节省了我的时间和精力 – Abhishek 2016-03-28 06:27:46

1

您必须提前知道什么样的对象将被反序列化。在这种情况下,您将要反序列化为NSDictionary,它有两个属性:“会计”和“销售”。每个属性都将是NSArray的一个实例。阵列将有NSDictionary的实例。

由于您知道这些对象中的每一个真的是,所以一旦将JSON反序列化为本机对象,您就可以从反序列化的对象中创建类的新实例。例如:

JSONDecoder decoder = [[JSONDecoder alloc] init]; 
NSObject notJSON = [decoder objectWithData:jsonData]; 
// where jsonData is an NSData representation of your JSON 
[decoder release]; 

Person person1 = (Person)[notJSON objectForKey:@"accounting"][0]; 

鉴于此示例,您应该能够推断出更通用的反序列化器。也就是说,您希望循环访问数据,以便将“未知”通用对象的深层副本创建为“已知”特定对象。

+1

对不起不是通用的。请参见[this](http://stackoverflow.com/questions/10515015/ios-json-serialization-for-nsobject-based-classes)以供参考 – 2013-02-19 13:51:53

+1

正如我所说的那样,正如您在参考文献中所述,这不是真的可行在此是完全通用的。 JSONKit已经解码为通用本机对象。这取决于你自己究竟是什么。如果你不能要求JSON告诉你(通过一些属性),那么你必须期望一个已知的格式。 – 2013-02-19 13:55:37

+0

我已经为此创建了一个更好的解决方案,但它仍然不能满足嵌套的JSON。一层嵌套的JSON没有问题。有了这个,我可以通过任何我想要序列化/反序列化的类。现在我打电话给任何人如果他们有任何想法如何为复杂的JSON做些什么 – 2013-02-19 14:01:07

0

也许这可以帮助BWJSONMatcher。 它可以帮助您用一行代码轻松地将JSON字符串或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]; 
...