我经常发现有必要来缓存创建的数据结构NSJSONSerialization
到磁盘和-writeToFile
如果有空失败,我需要在结构未知一个可行的修复。 这工作,并直接突变被允许以自己没有被列举的NSMutableDictionary的实例,但感觉有点哈克。
这是完全正常或者是绝对有必要重新创建一个新树,并返回?
- (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];
下面是我用清理我的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;
}
}
您可以通过将通过NSURLConnection的检索NSData的调用它。
NSArray *uableData = [utility cleanJsonToObject:data];
要么
NSDictionary *uableData = [utility cleanJsonToObject:data];
斯威夫特4版@Travis M.的回答;
class func removeNullFromJSONData(_ JSONData: Any) -> Any {
if JSONData as? NSNull != nil {
return JSONData
}
var JSONObject: Any!
if JSONData as? NSData != nil {
JSONObject = try! JSONSerialization.data(withJSONObject: JSONData, options: JSONSerialization.WritingOptions.prettyPrinted)
}
else {
JSONObject = JSONData
}
if JSONObject as? NSArray != nil {
let mutableArray: NSMutableArray = NSMutableArray(array: JSONObject as! [Any], copyItems: true)
let indexesToRemove: NSMutableIndexSet = NSMutableIndexSet()
for index in 0 ..< mutableArray.count {
let indexObject: Any = mutableArray[index]
if indexObject as? NSNull != nil {
indexesToRemove.add(index)
}
else {
mutableArray.replaceObject(at: index, with: removeNullFromJSONData(indexObject))
}
}
mutableArray.removeObjects(at: indexesToRemove as IndexSet)
return mutableArray;
}
else if JSONObject as? NSDictionary != nil {
let mutableDictionary: NSMutableDictionary = NSMutableDictionary(dictionary: JSONObject as! [AnyHashable : Any], copyItems: true)
for key in mutableDictionary.allKeys {
let indexObject: Any = mutableDictionary[key] as Any
if indexObject as? NSNull != nil {
mutableDictionary.removeObject(forKey: key)
}
else {
mutableDictionary.setObject(removeNullFromJSONData(indexObject), forKey: key as! NSCopying)
}
}
return mutableDictionary
}
else {
return JSONObject
}
}
+ (id)getObjectWithoutNullsForObject:(id)object
{
id objectWithoutNulls;
if ([object isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *dictionary = ((NSDictionary *)object).mutableCopy;
[dictionary removeObjectsForKeys:[dictionary allKeysForObject:[NSNull null]]];
for (NSString *key in dictionary.allKeys)
{
dictionary[key] = [self getObjectWithoutNullsForObject:dictionary[key]];
}
objectWithoutNulls = dictionary;
}
else if ([object isKindOfClass:[NSArray class]])
{
NSMutableArray *array = ((NSArray *)object).mutableCopy;
[array removeObject:[NSNull null]];
for (NSUInteger index = 0; index < array.count; index++)
{
array[index] = [self getObjectWithoutNullsForObject:array[index]];
}
objectWithoutNulls = array;
}
else if ([object isKindOfClass:[NSNull class]])
{
objectWithoutNulls = Nil;
}
else
{
objectWithoutNulls = object;
}
return objectWithoutNulls;
}