So your issue is:
Your server may return null
to indicate that an object isn't present. NSJSONSerialization
will convert that null
into an instance of NSNull
. In theory that means that instead of doing result[a][b][c]
you need to check whether result[a]
is a dictionary and, if so, whether result[a][b]
is a dictionary, etc, etc, which is repetitious and error-prone?
Perhaps the easiest thing might be to remove from the dictionary any key with a value of NSNull
, so that next time you ask for the value you'll get an ordinary nil
, which is safe to message per the usual compound-messaging rules?
NSJSONSerialization
won't do that for you but it's easy enough to add after the fact:
@interface NSDictionary(RemoveNullValues)
- (NSDictionary *)ty_collectionWithoutNullValues;
@end
@interface NSArray(RemoveNullValues)
- (NSArray *)ty_collectionWithoutNullValues;
@end
[...]
@implementation NSDictionary(RemoveNullValues)
- (NSDictionary *)ty_collectionWithoutNullValues {
NSMutableDictionary *reducedDictionary = [self mutableCopy];
// remove any keys for which NSNull is the direct value
NSArray *keysEvaluatingToNull = [self allKeysForObject:[NSNull null]];
[reducedDictionary removeObjectsForKeys:keysEvaluatingToNull];
// ask any child dictionaries to do the same; note that it's safe
// to mutate reducedDictionary in this array because allKeys is a
// copy property; what you're iterating is not reducedDictionary
// but a snapshot of its keys when the array first began
for (id key in [reducedDictionary allKeys]) {
id child = reducedDictionary[key];
if ([child respondsToSelector:@selector(ty_collectionWithoutNullValues)]) {
reducedDictionary[key] = [child ty_collectionWithoutNullValues];
}
}
return [reducedDictionary copy];
}
@end
@implementation NSArray(RemoveNullValues)
- (NSArray *)ty_collectionWithoutNullValues {
NSMutableArray *reducedArray = [NSMutableArray array];
for (id child in self) {
if ([child isKindOfClass:[NSNull class]]) continue;
if ([child respondsToSelector:@selector(ty_collectionWithoutNullValues)]) {
[reducedArray addObject:[child ty_collectionWithoutNullValues]];
} else {
[reducedArray addObject:child];
}
}
return [reducedArray copy];
}
@end