Mapping JSON objects in custom objects

风格不统一 提交于 2019-12-09 13:39:49

问题


I've been searching if it is possible to get a JSON dictionary or array and directly map it in a custom object whose properties have the same name as the JSON tags, but I din't find any information regarding that.

I've been parsing JSON dictionaries manually, like this:

id deserializedObj = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
                                                options:NSJSONReadingAllowFragments
                                                  error:&error];
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
        NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;

  if ([jsonDictionary objectForKey:idTag] != [NSNull null])
     [myObject setID:[[jsonDictionary objectForKey:@"id"] integerValue]];

  // Rest of properties
}

But I find weird having to parse each dictionary entry manually and not having a way to directly serialize it into a custom object, isn't there any other and faster way?

Note: I need my app to be compatible with iOS 5+

Thanks in advance


回答1:


I would propose you a library called Motis. It is a category on NSObject that does object mapping via KeyValueCoding. The nice thing of this category is that is very light-weight and performs automatic value validation trying to fit the class type of your properties (via introspection).

Most of all, what you have to do is define mappings (dictionaries) in your NSObject subclasses with pairs of "JSONKey": "PropertyName".

Also, if you have arrays, you can define mappings from your array names to the class types of its content enabling automatic object mapping for array content.

For example, If we try to map to our custom objects the following JSON:

{"video_id": 23,
 "video_title": "My holidays in Paris",
 "video_uploader":{"user_id":55,
                   "user_username": "johndoe"
                  },
 "video_people":[{"user_id":55,
                   "user_username": "johndoe"
                 },
                 {"user_id":45,
                   "user_username": "jimmy"
                 },
                 {"user_id":55,
                   "user_username": "martha"
                 }
                ]
 }

we would implement in our NSObject subclasses:

// --- Video Object --- //
@interface Video : NSObject
@property (nonatomic, assing) NSInteger videoId; 
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) User *uploader;
@property (nonatomic, strong) NSArray *peopleInVideo; // <-- Array of users
@end

@implementation Video
+ (NSDictionary*)mts_mapping
{
    return @{@"video_id" : mts_key(videoId),
             @"video_title" : mts_key(title),
             @"video_uploader" : mtsk_key(uploader),
             @"video_people": mts_key(peopleInVideo),
            };
}

+ (NSDictionary*)mts_arrayClassMapping
{
    return @{mts_key(peopleInVideo): User.class};
}

@end

// --- User Object --- //
@interface User : NSObject
@property (nonatomic, assing) NSInteger userId; 
@property (nonatomic, strong) NSString *username;
@end

@implementation User
+ (NSDictionary*)mts_mapping
{
    return @{@"user_id" : mts_key(userId),
             @"user_username" : mts_key(username),
            };
}

@end

And to perform the parsing and object mapping:

NSData *data = ... // <-- The JSON data
NSError *error = nil;
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

if (error)
    return; // if error, abort.

Video *video = [[Video alloc] init];
[video mts_setValuesForKeysInDictionary:jsonObject]; // <-- Motis Object Mapping 

NSLog(@"Video: %@", video.description);

That simple. Here you can read more about it: http://github.com/mobilejazz/Motis

For more information check the blog post on benefits of using KeyValueCoding and distributed object mapping I've wrote in MobileJazz blog.

Hoping to be helpful.




回答2:


You can try using JTObjectMapping inspired from RestKit.

The other way is to first remove null and nil values from dictionary. Create a mapping for your keys to keypath in your subclass using setValue:forKeyPath:




回答3:


You can create your own NSObject subclasses with their properties and populate them using Key-Value Coding in loop where you explore all NSDictionary keys returned from JSON deserialization. Of course each dictionary key should match an object property. Key value coding



来源:https://stackoverflow.com/questions/17929570/mapping-json-objects-in-custom-objects

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