Replace occurrences of NSNull in nested NSDictionary
A small modification to the method can make it recursive:
@interface NSDictionary (JRAdditions)
- (NSDictionary *) dictionaryByReplacingNullsWithStrings;
@end
@implementation NSDictionary (JRAdditions)
- (NSDictionary *) dictionaryByReplacingNullsWithStrings {
const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: self];
const id nul = [NSNull null];
const NSString *blank = @"";
for (NSString *key in self) {
const id object = [self objectForKey: key];
if (object == nul) {
[replaced setObject: blank forKey: key];
}
else if ([object isKindOfClass: [NSDictionary class]]) {
[replaced setObject: [(NSDictionary *) object dictionaryByReplacingNullsWithStrings] forKey: key];
}
}
return [NSDictionary dictionaryWithDictionary: replaced];
}
Note that the fast-enumeration is now on self
instead of replaced
With the code above, this example:
NSMutableDictionary *dic1 = [NSMutableDictionary dictionary];
[dic1 setObject: @"string 1" forKey: @"key1.1"];
[dic1 setObject: [NSNull null] forKey: @"key1.2"];
NSMutableDictionary *dic2 = [NSMutableDictionary dictionary];
[dic2 setObject: @"string 2" forKey: @"key2.1"];
[dic2 setObject: [NSNull null] forKey: @"key2.2"];
[dic1 setObject: dic2 forKey: @"key1.3"];
NSLog(@"%@", dic1);
NSLog(@"%@", [dic1 dictionaryByReplacingNullsWithStrings]);
renders this result:
2012-09-01 08:30:16.210 Test[57731:c07] {
"key1.1" = "string 1";
"key1.2" = "<null>";
"key1.3" = {
"key2.1" = "string 2";
"key2.2" = "<null>";
};
}
2012-09-01 08:30:16.212 Test[57731:c07] {
"key1.1" = "string 1";
"key1.2" = "";
"key1.3" = {
"key2.1" = "string 2";
"key2.2" = "";
};
It works for me, I used nested looping to replace all NULL with nil in the entire dictionary including NSArray.
- (NSDictionary *) dictionaryByReplacingNullsWithNil:(NSDictionary*)sourceDictionary {
NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:sourceDictionary];
const id nul = [NSNull null];
for(NSString *key in replaced) {
const id object = [sourceDictionary objectForKey:key];
if(object == nul) {
[replaced setValue:nil forKey:key];
}
}
return [NSDictionary dictionaryWithDictionary:replaced];
}
-(NSDictionary *) nestedDictionaryByReplacingNullsWithNil:(NSDictionary*)sourceDictionary
{
NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:sourceDictionary];
const id nul = [NSNull null];
const NSString *blank = @"";
[sourceDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
object = [sourceDictionary objectForKey:key];
if([object isKindOfClass:[NSDictionary class]])
{
NSDictionary *innerDict = object;
[replaced setObject:[self nestedDictionaryByReplacingNullsWithNil:innerDict] forKey:key];
}
else if([object isKindOfClass:[NSArray class]]){
NSMutableArray *nullFreeRecords = [NSMutableArray array];
for (id record in object) {
if([record isKindOfClass:[NSDictionary class]])
{
NSDictionary *nullFreeRecord = [self nestedDictionaryByReplacingNullsWithNil:record];
[nullFreeRecords addObject:nullFreeRecord];
}
}
[replaced setObject:nullFreeRecords forKey:key];
}
else
{
if(object == nul) {
[replaced setObject:blank forKey:key];
}
}
}];
return [NSDictionary dictionaryWithDictionary:replaced];
}