【问题标题】:How to remove a string containing "<null>" from an NSDictionary如何从 NSDictionary 中删除包含“<null>”的字符串
【发布时间】:2014-07-16 08:13:52
【问题描述】:

我有用户信息字典,它是从网络服务中获取的。有些字段的内容是私有的,因此它包含 NULL。如何将值转换为空字符串,只要有以下字典中的 null 值:

{
"about_me" = "<null>";
"contact_number" = 123456798798;
"display_name" = "err";
followers = 0;
following = 4;
gender = "-";
posts = 0;
"user_id" = 18;
username = charge;
website = "<null>";
}

【问题讨论】:

标签: ios iphone objective-c ios7


【解决方案1】:

更高级的解决方案:

@interface NSObject (NULLValidation)
- (BOOL)isNull ;
@end

@implementation NSObject (NULLValidation)

- (BOOL)isNull{
    if (!self) return YES;
    else if (self == [NSNull null]) return YES;
    else if ([self isKindOfClass:[NSString class]]) {
        return ([((NSString *)self)isEqualToString : @""]
                || [((NSString *)self)isEqualToString : @"null"]
                || [((NSString *)self)isEqualToString : @"<null>"]
                || [((NSString *)self)isEqualToString : @"(null)"]
                );
    }
    return NO;

}
@end


@interface NSDictionary (NullReplacement)
- (NSDictionary *) dictionaryByReplacingNullsWithString:(NSString*)string;
@end

@implementation NSDictionary (NullReplacement)

- (NSDictionary *) dictionaryByReplacingNullsWithString:(NSString*)string {
     NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary: self];

     NSString *blank = string;

    [self enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        if ([obj isNull]) {
            [replaced setObject:blank forKey: key];
        }
        else if ([obj isKindOfClass: [NSDictionary class]]) {
            [replaced setObject: [(NSDictionary *) obj dictionaryByReplacingNullsWithString:string] forKey: key];
        }
    }];

    return replaced ;
}
@end

【讨论】:

  • -1 因为 -isNull 有几个问题。首先,你没有使用多态性。您不应该在根类中有一个方法来测试实例是否属于子类。只需将所需的行为放在子类中。对于 NSNull,只返回 YES,对于 NSString,返回字符串比较的结果。其次,如果引用为 nil,则永远不应调用 -[NSObject isNull]。运行时不仅应该忽略它,而且数组元素和字典值默认抛出异常。这就是 NSNull 存在的原因,作为一种解决方法。
【解决方案2】:

最简单的方法是遍历字典的可变副本,如果值为
null 将值设置为你想要的值。

NSMutableDictionary *mutableDict = [dict mutableCopy];
for (NSString *key in [dict allKeys]) {
    if ([dict[key] isEqual:[NSNull null]]) {
        mutableDict[key] = @"";//or [NSNull null] or whatever value you want to change it to
    }
}
dict = [mutableDict copy];

如果字典中的值实际上是"&lt;null&gt;",则将条件替换为[dict[key] isEqualToString:@"&lt;null&gt;"]

(假设您使用的是 ARC,否则您需要发布已复制的字典)

【讨论】:

  • as @{ @"website":[NSNull null] } 打印 { website = "";} 我假设它不是字符串。
  • NSLog 不是为了将 NSNull 转换为有效的 JSON 值。如果打印 [NSNull null],则会打印“”。但是,如果你用 NSJSONSerialization 对其进行序列化,则该值被正确转换为 json null
  • 我只是说我认为字典中有一个 NSNull。
【解决方案3】:

首先,"&lt;null&gt;" 不是有效的 JSON 空值。
这么写,它只是一个包含单词&lt;null&gt;的字符串

在JSON中,null就是这样写的。

{ "value": null }

因此,如果您无法更新您的 Web 服务以返回有效的 json,我建议您首先对 JSON 字符串进行替换。 然后,当您有有效的 JSON 空值时,只需使用 NSJSONSerialization 处理它

NSString *json = @"{ \"value\": null }";
NSError *error = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];

NSLog(@"%@", jsonObject);

这会打印出来

2014-07-16 10:31:36.737 MacUtilities[30760:303] {
    value = "<null>";
}

以及调试value的类

po [[jsonObject objectForKey:@"value"] class];
NSNull

这是因为 NSJSONSerialization 正确处理 null,将其转换为 NSNull 实例

【讨论】:

  • 这个问题有很多反对意见,没有任何解释。不清楚为什么有人有时应该为这个网站贡献任何东西......
【解决方案4】:

Swift 3.0/4.0解决方案

以下是解决方案,当JSON 拥有sub-dictionaries。这将遍历所有dictionariesJSON 的子-dictionaries 并从JSON 中删除NULL(NSNull) key-value 对。

extension Dictionary {

    func removeNull() -> Dictionary {
        let mainDict = NSMutableDictionary.init(dictionary: self)
        for _dict in mainDict {
            if _dict.value is NSNull {
                mainDict.removeObject(forKey: _dict.key)
            }
            if _dict.value is NSDictionary {
                let test1 = (_dict.value as! NSDictionary).filter({ $0.value is NSNull }).map({ $0 })
                let mutableDict = NSMutableDictionary.init(dictionary: _dict.value as! NSDictionary)
                for test in test1 {
                    mutableDict.removeObject(forKey: test.key)
                }
                mainDict.removeObject(forKey: _dict.key)
                mainDict.setValue(mutableDict, forKey: _dict.key as? String ?? "")
            }
            if _dict.value is NSArray {
                let mutableArray = NSMutableArray.init(object: _dict.value)
                for (index,element) in mutableArray.enumerated() where element is NSDictionary {
                    let test1 = (element as! NSDictionary).filter({ $0.value is NSNull }).map({ $0 })
                    let mutableDict = NSMutableDictionary.init(dictionary: element as! NSDictionary)
                    for test in test1 {
                        mutableDict.removeObject(forKey: test.key)
                    }
                    mutableArray.replaceObject(at: index, with: mutableDict)
                }
                mainDict.removeObject(forKey: _dict.key)
                mainDict.setValue(mutableArray, forKey: _dict.key as? String ?? "")
            }
        }
        return mainDict as! Dictionary<Key, Value>
    }
 }

【讨论】:

    【解决方案5】:

    你有一个字典而不是一个数组。也许你有很多字典。枚举数组并对每个字典的键值对做空检查。

    您有一个可能来自 JSON 响应的解析 NSDictionary。 JSON 可能包含 null 值,并且您使用的 JSON 解析器将 null 转换为 [NSNull null],如果您尝试将字符串与该 NSNull 进行比较,则它不起作用。在这种情况下,试试这个:

    if ([yourDictionary objectForKey:@"website"]== [NSNull null]) {
        // handle here
    }
    

    【讨论】:

    • 仅供参考:[NSNull null] 与任何级别的@"&lt;null&gt;" 都不相同;而且这种比较在任何层面上都不是真正有效的。
    • 仅供参考:@{ @"website":[NSNull null] } 打印为 { website = "";} @holex
    • @holex ,仅供参考:@"" 不是字符串,这就是它 [NSNull null] 在控制台中打印的方式,正如 'vikingosegundo' 解释的那样。接受的答案证明了这一点。
    【解决方案6】:

    在 swift-4 而不是 remove 中,您可以使用以下方法将空值替换为空字符串

    func removeNullFromDict (dict : NSMutableDictionary) -> NSMutableDictionary
    {
        let dic = dict;
    
        for (key, value) in dict {
    
            let val : NSObject = value as! NSObject;
            if(val.isEqual(NSNull()))
            {
                dic.setValue("", forKey: (key as? String)!)
            }
            else
            {
                dic.setValue(value, forKey: key as! String)
            }
    
        }
    
        return dic;
    }
    

    在以以下方式将dict赋予任何方法调用函数之前

    let newdict = self.removeNullFromDict(dict: dict);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      • 2018-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多