views:

323

answers:

5

What I mean by generic is that you pass a class and a JSON to a method and that method transforms the JSON data in your object based on the class definition.
I'm interested both in conceptual answers and Objective-C approaches.

A: 

I dont know objective-c at all but i do know JSON.

Its a uniform data exchange format, with an RFC so you would definately be able to role your own parser. Does objective-c support generic types? If so what your looking for would be achievable, and id also guess that someone else has all ready rolled one.

Jammin
A: 

Well, conceptually, this method is known as serialization/deserialization. The difference is that your serialized format will be JSON. Realization: Define basic conventions for your class and JSON and implement them. For example: Every JSON should have uniq-id which will correspond to the class.

I'm not familiar with Objective-C, but if I would do that in other languages, I would assume, that every key in JSON, would represent the attribute of the class. This attribute could be set by function like classInstance.setJsonAttribute(key, value); Then, I would write some JSON parser which would walk through JSON, extracted uniq-id, created class based on this id, and walked through all other key:values parse, setting them with setJsonAttribute function. I think, that would be my begin in implementation.

nemisj
+1  A: 

I assume with generic parser, you mean an implicit JSON-to-object mapper.

In this case, there is one challenge. Which might or might not be solvable depending whether variables are types in Objective-C (it's actually a shame I dont know that). While its quite simple to map setter method names (given Objective-C does provide reflection) to jason attributes, it is hard to know which object to create for nested jason objects. So you need a kind of factory that guesses which type nested objects could have. If variables in Objective-C are types, that might be used as a hint, if not you are left on your own.

Adrian
A: 

You would need to use reflection on the passed in class which is not handled as well as some other languages from what i can see.

Class c = [self class];

Will return a C struct containing a list of variables and methods and then it would be a matter of writing a data mapper style system to reflect the class and assign the JSON variables to it.

E.g. JSON struct of

var x = { prop1: "Test 1",
          prop2: "Test 2};

Then have a class

@interface x  : NSObject {
       NSString* prop1;
       NSString* prop2;
}
@property (nonatomic,retain) NSString* prop1;
@property (nonatomic,retain) NSString* prop2;

You'd need to have a concrete implementation but it doesn't need to do anything fancy really.

Your mapper could then use either use reflection to parse the object or just use dumb assignment:

- (NSObject)mapClassFromJSON:(NSObject)class fromJSON:(id)jsonArray
{
//code needs to iterate over the jsonArray (needs to check using isKindOfClass if it's an NSArray or NSDictionary) and assign the class properties to it.
}

Remember if using SBJSON which everyone does, that the types inside the returned JSON can either be NSArray or NSDictionary, it needs to know which. If going down the generic path for nesting then it would need to use variable reflection and some smarts to generate the type mappings as otherwise it needs to be hard coded for each class.

Edit: Have a look at

http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple%5Fref/c/func/class%5FcopyPropertyList

Might be useful, might not...

Ben Sykes
A: 

Getting the data into NSArray and the like is easy, there are plenty of these around, for example json-framework

Try this (untested):

#import <Cocoa/Cocoa.h>
#import "JSON/JSON.h"

int main(int argc, char *argv[])
{
    NSLog(@"%@", [@"[ 100, 500, 300, 200, 400 ]" JSONValue]);
    return 0;
}

As Adrian says, mapping your data structures to objects is a bit of a challenge, then. It isn't in json-framework, I don't know what else there is. For sure, but I suppose that the project maintainer will accept your code, if you write some :).

nes1983