Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C DRY JSON Mapping and Object Creation

I am trying to dynamically map JSON information into different objects. But I can't figure out quite how to get the whole pointer situation under control, as what I was hoping would work does not.

So far my methodology has been to create a dictionary for each object, mapping the variable pointers to the equivalent JSON keys. In my JSON mapper, I have a method, parseJSONFromDictionary:withObject that is supposed to iterate over the dictionary returned by SBJSON's JSONValue and assign the appropriate values to the appropriate variables in the given object.

-(NSObject *)parseJSONFromDictionary:(NSDictionary *)dict withObject:(NSObject *)start{
    for (NSString *key in dict) {
        if ([[self.mappings objectForKey:key] isMemberOfClass:[NSString class]]) {
            start.[self.mappings objectForKey:key] = [[dict valueForKey:key] stringValue];
        }
    }
    return start;
}

mappings is the dictionary that has the variables and json keys, and the dict is what gets returned from the json parser.

The big problem is that I can't do start.[self.mappings objectForKey:key]. I don't know much about C, and clearly I don't know enough about pointers, so how would I go about creating this kind of system? I know that's not the right way to do this, but what is the right way? I know it can be done, as RestKit does it, but they don't support OAuth so I sadly can't use their lovely framework.

The reason I'm going this route is because the API I'm working with is currently in its alpha stage. I want to be able to easily adapt to any future changes without having to rewrite many lines of code. I also want to start programming DRY-ly. I know JSON parsing is very repetitive, and I'd like to find a way to reduce the amount of overhead.

Thanks for any and all help!


EDIT: It seems there is some confusion as to what I'm asking. I do not need help parsing JSON. I'm using SBJSON already. I do not need help making requests, I am already using JDG's OAuthConsumer framework. I can only use frameworks that support OAuth 2.0.

I do need help figuring out how to prevent this:

-(Class1 *)parseJsonForClass1:(NSString *)inputString {
    NSDictionary *outputDict = [inputString JSONValue];
    Class1 *instance1 = [self mapObjectsForClass1From:outputDict];
    return instance1;
}

-(Class2 *)parseJsonForClass2:(NSString *)inputString {
    NSDictionary *outputDict = [inputString JSONValue];
    Class2 *instance2 = [self mapObjectsForClass2From:outputDict];
    return instance2;
}

-(Class3 *)parseJsonForClass3:(NSString *)inputString {
    NSDictionary *outputDict = [inputString JSONValue];
    Class2 *instance3 = [self mapObjectsForClass3From:outputDict];
    return instance3;
}

-(Class1 *)mapObjectsForClass1From:(NSDictionary *)dict {
    Class1 *object1 = [[Class1 alloc] init];
    object1.name = [[dict valueForKey:@"name"] stringValue];
    object1.date = [[dict valueForKey:@"date"] stringValue];
    object1.objId = [[dict valueForKey:@"id"] intValue];

    return object1;
}

-(Class2 *)mapObjectsForClass2From:(NSDictionary *)dict {
    Class2 *object2 = [[Class2 alloc] init];
    object2.something = [[dict valueForKey:@"something"] stringValue];
    object2.title = [[dict valueForKey:@"title"] stringValue];
    object2.imageUrl = [[dict valueForKey:@"image_url"] stringValue];

    return object2;
}

-(Class3 *)mapObjectsForClass3From:(NSDictionary *)dict {
    Class3 *object3 = [[Class3 alloc] init];
    object3.foo = [[dict valueForKey:@"bar"] stringValue];
    object3.flag = [[dict valueForKey:@"is_member"] boolValue];
    object3.obj1 = [[Class1 alloc] init];
    object3.obj1 = [self mapOjectsForClass1From:[dict objectForKey:@"name1"]];

    return object3;
}

So please let me know if you have any suggestions on how to combine these kinds of methods into 1 method...

like image 307
MishieMoo Avatar asked Feb 11 '11 01:02

MishieMoo


3 Answers

I know this is an old thread but thought to put this here, the code here in https://github.com/mystcolor/JTObjectMapping would be able help in object mapping. You will want to have the mappings and your custom object ready before you use this. I found this on googling ....havent used it though. Need to try it out.

like image 93
anoop4real Avatar answered Oct 13 '22 12:10

anoop4real


You could use KVC. Create a setter for each value in the JSON dictionary that you want to insert into your object and use -setValue:forKey: to actually set the values e.g.

-(NSObject *)parseJSONFromDictionary:(NSDictionary *)dict withObject:(NSObject *)start
{
    for (NSString *key in [dict allKeys]) 
    {
        NSString* propertyName = [[self mappings] objectForKey: key];
        [start setValue: [dict objectForKey: key] forKey: propertyName];
        // the above line will throw an exception if start does not have a set accessor for property
    }
    return start;
}
like image 29
JeremyP Avatar answered Oct 13 '22 13:10

JeremyP


I actually recently saw someone doing this using Objective Resources. While it's a nice way to access objects, some of the implementation can get messy. And you have to use everything the server sends you, whether you like it or not. I'm going to stay away from this right now.

like image 21
MishieMoo Avatar answered Oct 13 '22 14:10

MishieMoo