NSObject+SimpleJson

Certainly the subject of JSON processing on iOS is fairly old-hat at this point. After all, Apple has provided native support for JSON serialization and parsing since the release of iOS 5. So why bring it up now?

Personally I’ve never been entirely happy with the implementation provided by Apple, and in particular their decision to build their API around NSData instead of NSString. Granted there’s probably a reason why Apple chose to go that route, and also a reason why they didn’t bother to provide convenience methods that allow people to work with whichever type they prefer. But as far as I’m concerned, JSON is a textual/non-binary data format, so therefore the natural iOS data structure to use for outputting and inputting JSON data is an NSString. Using NSData instead is counter-intuitive, and clunky as a result.

So because of that clunkiness, I’ve stuck with the tried and true SBJson library, even though the author of that library himself recommends just using Apple’s implementation. This preference is largely based around the very helpful (and also very deprecated) ‘NSObject+SBJson‘ category that is included in the library. This category imbues objects with a couple of very convenient methods:

- (NSString*)JSONRepresentation;
- (id)JSONValue;

These methods can be used to turn an appropriate object (i.e. an NSArray or an NSDictionary) into a JSON string, and to turn a JSON string back into a proper object, respectively. No parameters, no options, no boxing to or unboxing from NSData; just a simple API that is basically just ‘[thing turnIntoJson];‘ and ‘[json turnBackIntoThing];‘. It doesn’t get much more convenient than that.

And that was all well and good, until I wanted to build a framework which internally used SBJson, and then use that framework within a project that also needs to make its own use of SBJson. Linker hell was the result. And long story short, I decided that it would be faster to build a shim around Apple’s JSON API to preserve the convenience I’m after than it would be to appease the linker gods.

So in case anyone else has been avoiding Apple’s JSON implementation because it’s too clunky to work with (or too painful to migrate away from SBJson), here’s my 5-minute shim:

NSObject+SimpleJson.h

#import <Foundation/Foundation.h>

@interface NSObject (SimpleJson)

- (NSString *)JSONRepresentation;  //turns an object into a JSON string
- (id)JSONValue;                           //turns a JSON string back into an object

@end

NSObject+SimpleJson.m

#import "NSObject+SimpleJson.h"

@implementation NSObject (SimpleJson)

- (NSString*)JSONRepresentation {
    //write ourself to a JSON string; only works if we're a type that 'NSJSONSerialization' supports
    NSError* error = nil;
    NSData* tempData = [NSJSONSerialization dataWithJSONObject:self options:kNilOptions error:&error];
    if (error) {
        return nil;
    }
    
    return [[NSString alloc] initWithData:tempData encoding:NSUTF8StringEncoding];
}


- (id) JSONValue {
    //converts from a string back into a proper object; only works if we're an NSString or NSData instance
    if (! [self isKindOfClass:[NSString class]] && ! [self isKindOfClass:[NSData class]]) {
        return nil;
    }
    
    NSData* jsonData = nil;
    if ([self isKindOfClass:[NSData class]]) {
        jsonData = (NSData*)self;
    }
    else {
        //we must be an NSString
        jsonData = [((NSString*)self) dataUsingEncoding:NSUTF8StringEncoding];
    }
    
    return [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil];
}

@end

If you have code that uses SBJson’s ‘NSObject+SBJson‘ category, the above category should be drop-in compatible. And just as importantly (in my case) does not invoke linker hell when used as part of an iOS framework.

Note that the above code assumes you are using ARC. If not, you’ll want to add an ‘autorelease‘ call in there.

This entry was posted in coding, objective-c and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>