Question

We're using AFNetworking in our mobile app and a lot of times we will have JSON come back that has null for some values.

I'm getting tired of doing the following.

if ([json objectForKey:@"nickname"] isKindOfClass:[NSNull class]]) {
    nickname = nil;
} else {
    nickname = [json objectForKey:@"nickname"];
}

Anything we can do to make AFNetworking automagically set objects to nil or numbers to 0 if the value is null in the JSON response?

Was it helpful?

Solution

It's not really possible, since the dictionary can't contain nil as the object for a key. The key would have to be left out entirely in order to get the behavior you'd want, which would be undesirable in its own way.

Suppose you didn't have control over the data you were receiving and didn't know what keys were present in the JSON. If you wanted to list them all, or display them in a table, and the keys for null objects were left out of the dictionary, you'd be seeing an incorrect list.

NSNull is the "nothing" placeholder for Cocoa collections, and that's why it's used in this case.

You could make your typing a bit easier with a macro:

#define nilOrJSONObjectForKey(JSON_, KEY_) [[JSON_ objectForKey:KEY_] isKindOfClass:[NSNull class]] ? nil : [JSON_ objectForKey:KEY_]

nickname = nilOrJSONObjectForKey(json, @"nickname");

OTHER TIPS

You can set flag setRemovesKeysWithNullValues to YES in AFHTTPSessionManager response serializer:

AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithBaseURL:url sessionConfiguration:config];
AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
[serializer setRemovesKeysWithNullValues:YES];
[manager setResponseSerializer:serializer];

DV_'s answer works great for AFHTTPSessionManager. But if you are using AFHTTPRequestOperation instead of the manager, try this:

AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
serializer.removesKeysWithNullValues = YES;
op.responseSerializer = serializer;

There is one beautiful cocoapod called Minced https://github.com/hyperoslo/Minced that can do something that can help you handle NULL from JSON response. Instead of NULL it puts empty string.

If you replace the default NSJSONSerialization with SBJSON it will solve your problem.

SBJSON makes objects nil instead of NSJSONSerialization's choice of "null"

look at the requirements for the different JSON parsers you can use. https://github.com/AFNetworking/AFNetworking#requirements

You can custom AFNetworking at this functions. set any value default to objects that is NULL

static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) {
if ([JSONObject isKindOfClass:[NSArray class]]) {
    NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]];
    for (id value in (NSArray *)JSONObject) {
        [mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
    }

    return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
} else if ([JSONObject isKindOfClass:[NSDictionary class]]) {
    NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject];
    for (id <NSCopying> key in [(NSDictionary *)JSONObject allKeys]) {
        id value = (NSDictionary *)JSONObject[key];
        if (!value || [value isEqual:[NSNull null]]) {
            // custom code here
            //[mutableDictionary removeObjectForKey:key];
            [mutableDictionary setObject:@"" forKey:key];
        } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
            mutableDictionary[key] = AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions);
        }
    }

    return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
}

return JSONObject;

}

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top