objective-c - 递归地从 JSON 结构中删除空值

标签 objective-c recursion nsdictionary nsnull

我经常发现需要将 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 编写一个默认的无操作实现,并为 NSMutableArrayNSMutableDictionary 覆盖它:

// 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/

相关文章:

ios - PHAsset + AFNetworking。无法在真实设备上将文件上传到服务器

iphone - ARC奇怪的行为

r - Julia - 相当于 R 中的递归 sapply 函数

ios - NSMutableArray 中的 NSDictionary (iOS)

iphone - iOS 5 使用 NSDictionary 从发送的推送通知中检索信息

objective-c - 将图像数组(包装在 NSData 中)上传到 iOS 中的服务器

objective-c - 如何获得 MacOS 上特定用户的首选语言?

python - 在 Python3 的递归函数中使用 print()

c++ - C++ 中的自减运算符

ios - 如何使用 NSJSONSerialization