理想评论学派
理想评论学派

Reputation: 1001

How to convert JSON to Object

I defined some custom classes, such as Teacher, Student... Now I receive teacher info (JSON string) from remote server.

How can I convert the JSON string to Teacher object.

In Java, it's easy to implement a common method for all class (Teacher, Student...) with reflect.

But in Objective-C on iOS, the best way I can find is to use Entity of Core Data, which has setValue:forKey method. First I convert the JSON string to NSDictionary, the set the key-value pair in the disctionary to the Entry.

Is there any better ways?

(I'm from China, so maybe my English is poor, sorry!)

Upvotes: 10

Views: 5448

Answers (3)

范陆离
范陆离

Reputation: 91

Specifically, check out https://github.com/fanpyi/jsontooc/blob/master/README.md This is the example convert JSON data to Objective-C model, use nodejs.

Upvotes: 0

Adrian Rodriguez
Adrian Rodriguez

Reputation: 3242

These are all good frameworks for JSON parsing to dictionaries or other primitives, but if you're looking to avoid doing a lot of repetitive work, check out http://restkit.org . Specifically, check out https://github.com/RestKit/RestKit/blob/master/Docs/Object%20Mapping.md This is the example on Object mapping where you define mapping for your Teacher class and the json is automagically converted to a Teacher object by using KVC. If you use RestKit's network calls, the process is all transparent and simple, but I already had my network calls in place and what I needed was to convert my json response text to a User object (Teacher in your case) and I finally figured out how. If that's what you need, post a comment and I'll share how to do it with RestKit.

Note: I will assume the json is output using the mapped convention {"teacher": { "id" : 45, "name" : "Teacher McTeacher"}}. If it's not this way, but instead like this {"id" : 45, "name" : "Teacher McTeacher"} then don't worry ... object mapping design doc in the link shows you how to do this...a few extra steps, but not too bad.

This is my callback from ASIHTTPRequest

- (void)requestFinished:(ASIHTTPRequest *)request {
    id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:[request.responseHeaders valueForKey:@"Content-Type"]]; // i'm assuming your response Content-Type is application/json
    NSError *error;
    NSDictionary *parsedData = [parser objectFromString:apiResponse error:&error];
    if (parsedData == nil) {
        NSLog(@"ERROR parsing api response with RestKit...%@", error);
        return;
    }

    [RKObjectMapping addDefaultDateFormatterForString:@"yyyy-MM-dd'T'HH:mm:ssZ" inTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; // This is handy in case you return dates with different formats that aren't understood by the date parser

    RKObjectMappingProvider *provider = [RKObjectMappingProvider new];

    // This is the error mapping provider that RestKit understands natively (I copied this verbatim from the RestKit internals ... so just go with it
    // This also shows how to map without blocks
    RKObjectMapping* errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
    [errorMapping mapKeyPath:@"" toAttribute:@"errorMessage"];
    [provider setMapping:errorMapping forKeyPath:@"error"];
    [provider setMapping:errorMapping forKeyPath:@"errors"];

    // This shows you how to map with blocks
    RKObjectMapping *teacherMapping = [RKObjectMapping mappingForClass:[Teacher class] block:^(RKObjectMapping *mapping) {
        [mapping mapKeyPath:@"id" toAttribute:@"objectId"];
        [mapping mapKeyPath:@"name" toAttribute:@"name"];
    }];

    [provider setMapping:teacherMapping forKeyPath:@"teacher"];

    RKObjectMapper *mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:provider];
    Teacher *teacher = nil;
    RKObjectMappingResult *mappingResult = [mapper performMapping];
    teacher = [mappingResult asObject];

    NSLog(@"Teacher is %@ with id %lld and name %@", teacher, teacher.objectId, teacher.name);
}

You can obviously refactor this to make it cleaner, but that now solves all my problems.. no more parsing... just response -> magic -> Object

Upvotes: 5

NadavN7
NadavN7

Reputation: 367

First, do you use JSON Parser? (if not, i'd recommend using SBJson).

Second, why not create an initWithDictionary init method in your custom class that returns self object?

Upvotes: 6

Related Questions