Question

I have a series of NSObject's I would like to serialize to JSON and post to a service. The final object consists of several levels of these NSObject subclasses nested within each other.

Each one of these objects follows a protocol with a method which returns that objects properties in an NSDictionary with the appropriate keys. However, some of these properties are other objects and so forth, making the serialization a bit complicated.

Is there a pattern I could use to simplify serializing the final object? Using JSONKit, it seems I would need to serialize each dictionary individually from the deepest object and work backwards, checking for errors, then adding to a compound string. I know this can not possibly be the best method using this very capable library. Any suggestion or guidance is welcomed.

Edit 1

JSONKit GitHub URL

JSONKit Readme Documentation

Was it helpful?

Solution

I'm not sure I understand the problem. You ask for a pattern, but you seem to describe the standard one:

Each one of these objects follows a protocol with a method which returns that objects properties in an NSDictionary with the appropriate keys.

Let's say that method is called serializedDictionary. If a class has properties that are themselves other objects, you just call serializedDictionary and add the result to the dictionary you are building. So all you need to do is ask the top-level object for its serializedDictionary, and convert that to JSON.

If you're worried about error handling, just check the result of the method and pass the error up to your caller. You could do this with exceptions (no code to write) or by convention. For example, say on an error you return nil and also by-reference a pointer to an NSError instance. Then in your container objects you do something like this:

- (NSDictionary *)serializedDictionaryWithError:(NSError **)error
{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:self.someProperty forKey:@"some-property"];
    NSDictionary *childDict = [self.childObject serializedDictionaryWithError:error];
    if (childDict == nil) return nil;
    [dict setObject:childDict forKey:@"child-object"];
    return dict;
}

Bamn!

OTHER TIPS

The AutomagicCoding library uses low-level property introspection to recursively convert any NSObject into an NSDictionary, which can then be directly serialised as JSON:

https://github.com/psineur/NSObject-AutomagicCoding

It may involve a bit of fine-tuning for classes with properties that are structs, etc, but it's probably the easiest, least labour-intensive approach you'll find.

UPDATE:

I've since written my own library, HRCoding (https://github.com/nicklockwood/HRCoder) that can load/save any object as JSON using the NSCoding protocol)

Now you can solve this problem easily using JSONModel. JSONModel is a library that generically serialize/deserialize your object based on Class. You can even use non-nsobject based for property like int, short and float. It can also cater nested-complex JSON. It handles error checking for you.

Given this JSON {"firstname":"Jenson","surname":"Button"}

Deserialize example. in header file:

#import "JSONModel.h"

@interface Person : JSONModel 
@property (nonatomic, strong) NSString* firstname;
@property (nonatomic, strong) NSString* surname;
@end

in implementation file:

#import "JSONModelLib.h"
#import "yourPersonClass.h"

NSString *responseJSON = /*from somewhere*/;
Person *person = [[Person alloc] initWithString:responseJSON error:&err];
if (!err)
{
   NSLog(@"%@  %@", person.firstname, person.surname):
}

Serialize Example. In implementation file:

#import "JSONModelLib.h"
#import "yourPersonClass.h"

Person *person = [[Person alloc] init];
person.firstname = @"Jenson";
person.surname = @"Uee";

NSLog(@"%@", [person toJSONString]);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top