Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
578 views
in Technique[技术] by (71.8m points)

objective c - iOS JSON serialization for NSObject-based classes

I'd like to JSON-serialize my own custom classes. I'm working in Objective-C / iOS5. I'd like something to do the following:

Person* person = [self getPerson ]; // Any custom object, NOT based on NSDictionary
NSString* jsonRepresentation = [JsonWriter stringWithObject:person ];
Person* clone = [JsonReader objectFromJson: jsonRepresentation withClass:[Person Class]];

It seems that NSJSONSerialization (and several other libraries) require the 'person' class to be based on NSDictionary etc. I want something that will serialize any custom object that I care to define (within reason).

Let's imagine Person.h looks like this:

#import <Foundation/Foundation.h>
@interface Person : NSObject 
@property NSString* firstname;
@property NSString* surname;
@end

I'd like the generated JSON for an instance to look similar to the following:

{"firstname":"Jenson","surname":"Button"}

My app uses ARC. I need something that will both serialise and deserialize using objects.

Many thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is a tricky one because the only data you can put into JSON are straight up simple objects (think NSString, NSArray, NSNumber…) but not custom classes or scalar types. Why? Without building all sorts of conditional statements to wrap all of those data types into those type of objects, a solution would be something like:

//at the top…
#import <objC/runtime.h>

    NSMutableDictionary *muteDictionary = [NSMutableDictionary dictionary];

    id YourClass = objc_getClass("YOURCLASSNAME");
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(YourClass, &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        SEL propertySelector = NSSelectorFromString(propertyName);
        if ([classInstance respondsToSelector:propertySelector]) {
            [muteDictionary setValue:[classInstance performSelector:propertySelector] forKey:propertyName];
        }
    }
    NSError *jsonError = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:muteDictionary options:0 error:&jsonError];

This is tricky, though because of what I stated before. If you have any scalar types or custom objects, the whole thing comes tumbling down. If it's really critical to get something like this going, I'd suggest looking into investing the time and looking at Ricard's links which allow you to see property types which would assist on the conditional statements needed to wrap the values into NSDictionary-safe objects.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...