iOS: Serialize/Deserialize complex JSON generically from NSObject class

若如初见. 提交于 2019-12-17 04:34:19

问题


Anyone have idea how to serialize nested JSON based on NSObject class? There is a discussion to serialize simple JSON here , but it is not generic enough to cater complex nested JSON.

Imagine this is the result of 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 }
                  ]}

From this class:

@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

How to serialize/deserialize them based on class generically?

EDIT

Currently i'm able to generate payload like this based on any class:

NSMutableDictionary *Payload = [self serialize:objClass];

But it does not cater nested complex JSON. Anyone have better solution for this? This library for C# cater serialize/deserialze based on object class. I want to reproduce something the same based on NSObject


回答1:


Finally we can solve this problem easily using JSONModel. This is the best method so far. JSONModel is a library that generically serialize/deserialize your object based on Class. You can even use non-nsobject based for property like int, short and float. It can also cater nested-complex JSON.

1) Deserialize example. By referring to above example, in header file:

#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

in implementation file:

#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) Serialize Example. In implementation file:

#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]);

And this is NSLog result from Serialize example:

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



回答2:


You must know ahead of time what sort of object you will be deserializing. In this case, you're going to be deserializing to an NSDictionary that has two properties: "accounting" and "sales". Each of these properties will be an instance of NSArray. The arrays will have instances of NSDictionary.

Since you know what each of these objects really are, once you have deserialized the JSON into native objects you can create new instances of your classes out of the deserialized objects. For example:

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];

Given this example, you should be able to extrapolate to a more generic deserializer. That is, you'd want to loop through your data to create a deep copy of your "unknown" generic object to a "known" specific object.




回答3:


Maybe this one can help BWJSONMatcher. It helps you easily match a JSON string or JSON object up with your data model with one line of code.

...
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];
...


来源:https://stackoverflow.com/questions/14958883/ios-serialize-deserialize-complex-json-generically-from-nsobject-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!