我经常发现需要将 NSJSONSerialization
创建的数据结构缓存到磁盘,并且如果存在空值,-writeToFile
会失败,我需要一个修复程序,当结构未知。
这是有效的,并且允许直接突变,因为 NSMutableDictionary 的实例本身没有被枚举,但感觉有点 hacky。
这完全没问题还是绝对有必要重新创建一棵新树并返回它?
- (void) removeNullsFromJSONTree:(id) branch
{
if ([branch isKindOfClass:[NSMutableArray class]])
{
//Keep drilling to find the leaf dictionaries
for (id childBranch in branch)
{
[self removeNullsFromJSONTree:childBranch];
}
}
else if ([branch isKindOfClass:[NSMutableDictionary class]])
{
const id nul = [NSNull null];
const NSString *empty = @"";
for(NSString *key in [branch allKeys])
{
const id object = [branch objectForKey:key];
if(object == nul)
{
[branch setObject:empty forKey:key];
}
}
}
}
最佳答案
您的一般方法没有任何问题。由于NSNull
是一个单例,所以通过指针比较来寻找它就可以了。
但是,您并没有对字典中的值进行递归。通常,这些值本身可能是数组或字典。也许在你的具体情况下你知道他们不是。但如果可能的话,您需要对字典中的每个值执行 removeNullsFromJSONTree:
。
您也不要在数组中寻找 NSNull
。你应该?处理起来很简单:
[branch removeObject:[NSNull null]];
removeObject:
方法删除参数的所有实例。
我个人不喜欢显式测试对象类,因为我可以使用类别让消息发送系统为我做这件事。因此,我可能会像这样在 NSObject
上定义一个类别:
// NSObject+KezRemoveNulls.h
@interface NSObject (KezRemoveNulls)
- (void)Kez_removeNulls;
@end
我会为 NSObject
编写一个默认的无操作实现,并为 NSMutableArray
和 NSMutableDictionary
覆盖它:
// NSObject+KezRemoveNulls.m
#import "NSObject+KezRemoveNulls.h"
@implementation NSObject (KezRemoveNulls)
- (void)Kez_removeNulls {
// nothing to do
}
@end
@implementation NSMutableArray (KezRemoveNulls)
- (void)Kez_removeNulls {
[self removeObject:[NSNull null]];
for (NSObject *child in self) {
[child Kez_removeNulls];
}
}
@end
@implementation NSMutableDictionary (KezRemoveNulls)
- (void)Kez_removeNulls {
NSNull *null = [NSNull null];
for (NSObject *key in self.allKeys) {
NSObject *value = self[key];
if (value == null) {
[self removeObjectForKey:key];
} else {
[value Kez_removeNulls];
}
}
}
@end
请注意,所有实现代码仍在一个文件中。
现在我可以这样说了:
id rootObject = [NSJSONSerialization JSONObjectWithData:...];
[rootObject Kez_removeNulls];
关于objective-c - 递归地从 JSON 结构中删除空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16312879/