6

I'm mapping JSON-formatted data from a web server to Objective C classes (NSManagedObjects modeled in Xcode, handled by Core Data). For each attribute of the Objective C class, I need to:

  1. Determine if the attribute's key exists in the JSON object,
  2. Determine if the value for that key is not null, and
  3. Pass the value to the modeled class instance if conditions 1 and 2 are true

Right now, I'm hard-coding this sequence for each of the attributes, so every attribute needs code like the following:

// dictObject is the JSON object converted into a NSDictionary,
// and person is the instance of the modeled class

if ([dictObject objectForKey:@"nameFirst"] &&
    [dictObject objectForKey:@"nameFirst"] != [NSNull null]) {
    person.nameFirst = [dictObject objectForKey:@"nameFirst"];
}

Besides requiring a lot of code to handle the various classes, this seems kludgy and brittle: any name change (or language localization) would cause the mapping to fail.

There has to be a better way... what am I missing?

3 Answers 3

11

For handling the NULL values, make use of a category on NSDictionary. I use a category that looks like this:

NSDictionary+Utility.h

#import <Foundation/Foundation.h>


@interface NSDictionary (Utility) 
- (id)objectForKeyNotNull:(id)key;
@end

NSDictionary+Utility.m

#import "NSDictionary+Utility.h"


@implementation NSDictionary (Utility)

- (id)objectForKeyNotNull:(NSString *)key {
   id object = [self objectForKey:key];
   if ((NSNull *)object == [NSNull null] || (CFNullRef)object == kCFNull)
      return nil;

   return object;
}

@end

Retrieve any values from your JSON dictionary like this:

NSString *stringObject = [jsonDictionary objectForKeyNotNull:@"SomeString"];
NSArray *arrayObject = [jsonDictionary objectForKeyNotNull:@"SomeArray"];
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, Wolfgang—this is actually really helpful. I'm going to accept pokstad's answer because it's more robust, but I'll definitely make use of this pattern as well.
10

There is a framework called RestKit that allows you to do just that. I have not tested it but it appears to be supported by an active company and available as open source: http://restkit.org/

6 Comments

Thanks pokstad—hadn't seen that before. I downloaded RestKit and have been playing with it... it does add a lot of bulk to the app—36MB for the source folder!—but may well be worth it. Will definitely accept your answer if I use it. (I'm still hoping someone will reply with a more "native" approach.)
No problem. Not sure what you mean by native. That ReskKit is specifically made for Cocoa based apps. Also, the source code size is almost always larger than the binary size so I wouldn't worry about the 36MB as far as your compiled binary size is concerned.
Fair enough—RestKit looks like an excellent solution but if I implement it I'll be learning how to implement RestKit, rather than learning better Obj-C skills :) (Though one could of course argue that learning to implement frameworks well is learning Obj-C better.)
Don't worry, you'll still need to know lots of Objective-C to actually utilize the framework ;)
Digging deep into Restkit for the moment, seems very promising. Seems a common pattern in iOS to me, hopefully I need not to reinvent the wheel this time in my dirty way.
|
1

As a lightweight alternative to RestKit, you might try GoldenFleece, which converts between JSON and Objective-C objects using a convention-over-configuration pattern inspired by Jackson.

Disclaimer: I'm the author.

1 Comment

You should add a disclosure if it's your own library that you're pushing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.