Tij*_*Kez 4 recursion objective-c 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];
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
rob*_*off 13
你的一般方法没有错.既然NSNull是单身,那么可以通过指针比较来寻找它.
但是,您没有对字典中的值进行递归.通常,这些值可能是数组或字典本身.也许在你的具体情况下,你知道他们不是.但如果可能,您需要对removeNullsFromJSONTree:字典中的每个值执行操作.
你也不NSNull在数组中寻找.你应该?处理起来很简单:
[branch removeObject:[NSNull null]];
Run Code Online (Sandbox Code Playgroud)
该removeObject:方法删除参数的所有实例.
我个人不喜欢显式测试对象类,当我可以使用类别让消息发送系统为我做.所以我可能会NSObject像这样定义一个类别:
// NSObject+KezRemoveNulls.h
@interface NSObject (KezRemoveNulls)
- (void)Kez_removeNulls;
@end
Run Code Online (Sandbox Code Playgroud)
我会写一个默认的do-nothing实现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
Run Code Online (Sandbox Code Playgroud)
请注意,所有实现代码仍在一个文件中.
现在我可以这样说:
id rootObject = [NSJSONSerialization JSONObjectWithData:...];
[rootObject Kez_removeNulls];
Run Code Online (Sandbox Code Playgroud)
Tra*_* M. 10
这是我用来清理我的JSON调用的代码,似乎运行良好,但是,由于涉及一些处理开销,我实际上只在我无法在服务器上进行空值处理的情况下使用它.NSNull崩溃是我们最大的应用程序崩溃问题.
+ (id)cleanJsonToObject:(id)data {
NSError* error;
if (data == (id)[NSNull null]){
return [[NSObject alloc] init];
}
id jsonObject;
if ([data isKindOfClass:[NSData class]]){
jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
} else {
jsonObject = data;
}
if ([jsonObject isKindOfClass:[NSArray class]]) {
NSMutableArray *array = [jsonObject mutableCopy];
for (int i = array.count-1; i >= 0; i--) {
id a = array[i];
if (a == (id)[NSNull null]){
[array removeObjectAtIndex:i];
} else {
array[i] = [self cleanJsonToObject:a];
}
}
return array;
} else if ([jsonObject isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *dictionary = [jsonObject mutableCopy];
for(NSString *key in [dictionary allKeys]) {
id d = dictionary[key];
if (d == (id)[NSNull null]){
dictionary[key] = @"";
} else {
dictionary[key] = [self cleanJsonToObject:d];
}
}
return dictionary;
} else {
return jsonObject;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过传递通过NSURLConnection检索的NSData来调用它.
NSArray *uableData = [utility cleanJsonToObject:data];
Run Code Online (Sandbox Code Playgroud)
要么
NSDictionary *uableData = [utility cleanJsonToObject:data];
Run Code Online (Sandbox Code Playgroud)