replace嵌套的NSDictionary中的NSNull的发生

这个问题类似于这个问题 ,但是这个方法只能在字典的根级别上工作。

我正在寻找用空stringreplace任何NSNull值的发生,以便我可以将完整的字典保存为一个plist文件(如果我添加它与NSNull的文件将不会写入)。

然而,我的字典里面embedded了字典。 喜欢这个:

 "dictKeyName" = { innerStrKeyName = "This is a string in a dictionary"; innerNullKeyName = "<null>"; innerDictKeyName = { "innerDictStrKeyName" = "This is a string in a Dictionary in another Dictionary"; "innerDictNullKeyName" = "<null>"; }; }; 

如果我使用:

 @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 replaced) { const id object = [self objectForKey:key]; if(object == nul) { [replaced setObject:blank forKey:key]; } } return [NSDictionary dictionaryWithDictionary:replaced]; } @end 

我得到这样的东西:

 "dictKeyName" = { innerStrKeyName = "This is a string in a dictionary"; innerNullKeyName = ""; <-- this value has changed innerDictKeyName = { "innerDictStrKeyName" = "This is a string in a Dictionary in another Dictionary"; "innerDictNullKeyName" = "<null>"; <-- this value hasn't changed }; }; 

有没有从包括嵌套字典在内的所有字典中查找每个NSNull值的方法…?

编辑:数据是从一个JSON提要绘制的,所以我收到的数据是dynamic的(我不想每次更改提要都必须更新应用程序)。

该方法的一个小修改可以使其recursion:

 @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]; } 

请注意,快速枚举现在在self而不是replaced

用上面的代码,这个例子:

 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]); 

呈现这个结果:

 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" = ""; }; 

它适用于我,我用整个字典包括NSArray中使用嵌套循环来replace所有NULL与零。

 - (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]; } 

如果有人需要这个快速1.2,这里是片段:

 class func removeNullsFromDictionary(origin:[String:AnyObject]) -> [String:AnyObject] { var destination:[String:AnyObject] = [:] for key in origin.keys { if origin[key] != nil && !(origin[key] is NSNull){ if origin[key] is [String:AnyObject] { destination[key] = self.removeNullsFromDictionary(origin[key] as! [String:AnyObject]) } else if origin[key] is [AnyObject] { let orgArray = origin[key] as! [AnyObject] var destArray: [AnyObject] = [] for item in orgArray { if item is [String:AnyObject] { destArray.append(self.removeNullsFromDictionary(item as! [String:AnyObject])) } else { destArray.append(item) } } destination[key] = destArray } else { destination[key] = origin[key] } } else { destination[key] = "" } } return destination } 

这个代码

 @interface NSDictionary (JRAdditions) - (NSDictionary *) dictionaryByReplacingNullsWithStrings; @end 

猴子补丁NSDictionary – 这意味着你可以调用dictionaryByReplacing …不只是在根,但任何嵌套的字典,只要你愿意。

我从devise的angular度来看并不认同这一点,但它确实能解决您的问题。

尝试这个:

 @interface NSDictionary (JRAdditions) - (NSDictionary *) dictionaryByReplacingNullsWithStrings; -(NSDictionary *) nestedDictionaryByReplacingNullsWithStrings; @end @implementation NSDictionary (JRAdditions) - (NSDictionary *) dictionaryByReplacingNullsWithStrings { const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:self]; const id nul = [NSNull null]; const NSString *blank = @""; for(NSString *key in replaced) { const id object = [self objectForKey:key]; if(object == nul) { [replaced setObject:blank forKey:key]; } } return [NSDictionary dictionaryWithDictionary:replaced]; } -(NSDictionary *) nestedDictionaryByReplacingNullsWithStrings { const NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:self]; const id nul = [NSNull null]; const NSString *blank = @""; for(id *item in replaced) { const id object = [self objectForKey:key]; if([object isKindofClass:[NSDictionary class]]) { NSDictionary *innerDict = object; [replaced setObject:[innerDict dictionaryByReplacingNullsWithStrings] forKey:key]; } else { if(object == nul) { [replaced setObject:blank forKey:key]; } } } return [NSDictionary dictionaryWithDictionary:replaced]; } 

这个解决scheme适用于数组和字典,也适用于嵌套数组和字典等(recursion)。

 - (NSDictionary *)writableDictionary:(NSDictionary *)dictionary { NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary]; for (id key in mutableDictionary.allKeys) { id value = mutableDictionary[key]; mutableDictionary[key] = [self writableValue:value]; } return mutableDictionary; } - (NSArray *)writableArray:(NSArray *)array { NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array]; for (int i = 0; i < mutableArray.count; ++i) { id value = mutableArray[i]; mutableArray[i] = [self writableValue:value]; } return mutableArray; } - (id)writableValue:(id)value { if ([value isKindOfClass:[NSNull class]]) { value = @""; } else if ([value isKindOfClass:[NSDictionary class]]) { value = [self writableDictionary:value]; } else if ([value isKindOfClass:[NSArray class]]) { value = [self writableArray:value]; } return value; } 

如果你的字典里有数组,那么上面提到的答案就不会适应这种情况。 看一下这个

 +(NSMutableDictionary*)getValuesWithOutNull:(NSDictionary *)yourDictionary{ NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: yourDictionary]; id nul = [NSNull null]; NSString *blank = @""; for (NSString *key in yourDictionary) { const id object = [yourDictionary objectForKey: key]; if (object == nul) { [replaced setObject: blank forKey: key]; } else if ([object isKindOfClass: [NSDictionary class]]) { [replaced setObject:[self getValuesWithOutNull:object] forKey:key]; } else if([object isKindOfClass: [NSArray class]]) { NSMutableArray *array = [NSMutableArray arrayWithArray:object]; for(int i = 0 ;i < array.count;i++) { NSDictionary *dict = [array objectAtIndex:i]; [array replaceObjectAtIndex:i withObject:[self getValuesWithOutNull:dict]]; } [replaced setObject:array forKey:key]; } } return replaced; } 

以下方法完美地适用于任何数量的字典嵌套arrray:

 - (NSMutableDictionary *)dictionaryByReplacingNullsWithStrings:(NSDictionary *)jobList { NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:jobList]; const id nul = [NSNull null]; const NSString *blank = @""; for (NSString *key in [replaced allKeys]) { id object = [replaced objectForKey:key]; if (object == nul) { [replaced setObject:blank forKey:key]; } else if ([object isKindOfClass:[NSDictionary class]]) { [replaced setObject:[self replaceNullInNested:object] forKey:key]; } else if ([object isKindOfClass:[NSArray class]]) { NSMutableArray *dc = [[NSMutableArray alloc] init]; for (NSDictionary *tempDict in object) { [dc addObject:[self dictionaryByReplacingNullsWithStrings:tempDict]]; } [replaced setObject:dc forKey:key]; } } return replaced; } - (NSMutableDictionary *)replaceNullInNested:(NSDictionary *)targetDict { // make it to be NSMutableDictionary in case that it is nsdictionary NSMutableDictionary *m = [targetDict mutableCopy]; NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:m]; const id nul = [NSNull null]; const NSString *blank = @""; for (NSString *key in [replaced allKeys]) { const id object = [replaced objectForKey:key]; if (object == nul) { [replaced setObject:blank forKey:key]; } else if ([object isKindOfClass:[NSArray class]]) { // NSLog(@"found null inside and key is %@", key); // make it to be able to set value by create a new one NSMutableArray *a = [object mutableCopy]; for (int i = 0; i < [a count]; i++) { for (NSString *subKey in [[a objectAtIndex:i] allKeys]) { if ([[object objectAtIndex:i] valueForKey:subKey] == nul) { [[object objectAtIndex:i] setValue:blank forKey:subKey]; } } } // replace the updated one with old one [replaced setObject:a forKey:key]; } } return replaced; } 

我按照我所需的function使用上面的修改方法:

//调用方法NSMutableDictionary * sortedDict = [[NSMutableDictionary alloc] init];

for(NSString * key in jobList){NSMutableArray * tempArray = [[NSMutableArray alloc] init];

  for (NSDictionary *tempDict in [jobList objectForKey:key]) { [tempArray addObject:[self dictionaryByReplacingNullsWithStrings:tempDict]]; } [sortedDict setObject:tempArray forKey:key]; }