1
votes

I'm evaluating RestKit to use in my project. I've created a simple app that loads some JSON and maps it into Objective-C objects. I'm having a problem correctly mapping a JSON object that has numeric and logical fields. E.g.

{
   "integerValue":"5",
   "booleanValue":"YES",
}

I want these to map to the following properties in my data object:

@property int integerValue;
@property BOOL booleanValue;

It didn't work out of the box, so I've created a value transformer for that:

    [_activityMapping setValueTransformer:[RKBlockValueTransformer valueTransformerWithValidationBlock:^BOOL(__unsafe_unretained Class inputValueClass, __unsafe_unretained Class outputValueClass) {
        if([inputValueClass isSubclassOfClass:[NSString class]] && [outputValueClass isSubclassOfClass:[NSNumber class]])  {
            return YES;
        }
        else {
            return NO;
        }
    } transformationBlock:^BOOL(id inputValue, __autoreleasing id *outputValue, __unsafe_unretained Class outputClass, NSError *__autoreleasing *error) {
        if([[inputValue class] isSubclassOfClass:[NSString class]] && [outputClass isSubclassOfClass:[NSNumber class]]) {
            NSString *inputString = (NSString *)inputValue;
            if([inputString isEqualToString:@"YES"] || [inputString isEqualToString:@"NO"]) {
                *outputValue = [NSNumber numberWithBool:[inputString boolValue]];
            }
            else {
                *outputValue = [NSNumber numberWithInt:[inputString intValue]];
            }
        }
        else {
            *outputValue = [inputValue copy];
        }
        return YES;
    }]];

This code works, but looks ugly. Note how I have to check the input value to see if it's a boolean or an integer. Any suggestions on an elegant solution to this problem?

Please note that I'm using RestKit. I do know about NSJSONSerialization and know how to parse JSON in code. If you suggest a non-RestKit solution, please explain why do you not recommend using RestKit.

2
Can you fix the JSON which is incorrect? Boolean values in JSON are represented with true/false not YES/NO. If these were represented correctly then I believe RestKit would do the right thing - Paul.s
@Paul.s: you're spot on sir. Once I changed my JSON as you suggested, it started working without any custom value transforms. Wish I had thought of that sooner :) If you post your comment as answer, I'll be happy to accept it. - TotoroTotoro
@VarunVarahabotla Since I first asked this question, I've stopped using RestKit in favor of Mantle, and couldn't be happier. - TotoroTotoro
So is there a "Mantle" way of performing the same ValueTransforming function? It's kind of ridiculous that I can't even output a boolean value... - Varun Varahabotla

2 Answers

2
votes

The issue is not occurring at the RestKit level but at the JSON level itself.

According to the JSON spec Boolean values should be represented with true/false not YES/NO. If you update your JSON to be semantically correct then RestKit should do the right thing.

0
votes

Ok. So according to my understanding of your answer, your main problem lies in mapping the data in the JSON object to their very own designated variables.

So, I'd recommend using the conventional NSJSONSerialization approach.

So, first up. You need to store your JSON object in an NSData object. Now, you're most likely downloading the data from a simple URL. So, this is what you'd do :

//This part is just to download the data. If you're using another method - that's fine. Just make sure that the download is in NSData format
    NSURL *url = [[NSURL alloc] initWithString : @"YOUR_URL_HERE"];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL : url];
    NSData *jsonData = [NSURLConnection sendSynchronousRequest:request
                                             returningResponse:nil
                                                         error:nil];

Now, you need to map those to the NSDictionary... Here's how :

//This is the actual NSJSONSerialization part.
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData
                                                             options:NSJSONReadingMutableLeaves
                                                               error:nil];

Now, just map the values to your designated properties.

_integerValue = (int)[jsonDict objectForKey:@"integerValue"];
_booleanValue = (BOOL)[jsonDict objectForKey:@"booleanValue"];