swift - 从嵌套字典中删除或替换 <null> 值

Posted

技术标签:

【中文标题】swift - 从嵌套字典中删除或替换 <null> 值【英文标题】:swift - delete or replace <null> values from nested dictionary 【发布时间】:2019-09-30 13:29:45 【问题描述】:

我有一些来自服务器的数据,我正在使用Alamofire SwiftyJSON 将其转换为[String: Any]。然后我使用SwiftyPlistManager 将其保存到 plist。重点是SwiftyPlistManager在保存&lt;null&gt;的时候崩溃了,所以我需要把&lt;null&gt;或者nil全部替换成""

Alamofire SwiftyJSON 之后的我的字典是这样的:

["info_editable": true,
 "name": android Q,
 "is_message": true,
 "images": [["id": 92,
             "image": /media/product/102.png]],
 "video_description": <null>,
 "is_valid": true]

或者它可能是-

["info_editable": true,
 "name": Android Q,
 "is_message": true,
 "images": <null>,
 "video_description": <null>,
 "is_valid": true]

我想从原始数据中使用Codable,但不知道如何将初始值设置为空字符串或[[]],然后检查parced数据是否为&lt;null&gt;并将初始值保留为默认值。 或者有没有办法列出嵌套字典来替换&lt;null&gt;to ""

【问题讨论】:

var updatedDictionary = Dictionary(uniqueKeysWithValues: yourDictionary.map ($0, $1 != nil ? $1! : "") ) 【参考方案1】:

你可以试试

var dic = ["1":nil,"2":"33","3":"5444"]
let res = dic.mapValues  $0 == nil ? "" : $0 
print(res) // ["1": Optional(""), "2": Optional("33"), "3": Optional("5444")]

【讨论】:

【参考方案2】:

目前,我最好的想法是 -

1) 字符串化除字典数组之外的每个值,

2) 检查字符串内容是否为“null”,然后将其替换为""如果为真。

3) 字典数组,如果字符串化,将有 2 个选项 - 使用 [[]](然后像上面一样检查每个字典)或不使用 - 如果是 "images": &lt;null&gt;,(所以 &lt;null&gt; 应该被替换与[[]]。 但是我有大约 7 个不同数据的请求,应该以这种奇怪的方式解析,我希望找到更漂亮的决定。

【讨论】:

【参考方案3】:

这是一个协议解决方案,它递归地通过字典和数组:

/// Allows clients to ask the receiver to remove any `NSNull` instances
protocol NullStripable 
    func strippingNulls() -> Self


extension Array: NullStripable 
    func strippingNulls() -> Self 
        return compactMap 
            switch $0 
            case let strippable as NullStripable:
                // the forced cast here is necessary as the compiler sees
                // `strippable` as NullStripable, as we casted it from `Element`
                return (strippable.strippingNulls() as! Element)
            case is NSNull:
                return nil
            default:
                return $0
            
        
    


extension Dictionary: NullStripable 
    func strippingNulls() -> Self 
        return compactMapValues 
            switch $0 
            case let strippable as NullStripable:
                // the forced cast here is necessary as the compiler sees
                // `strippable` as NullStripable, as we casted it from `Value`
                return (strippable.strippingNulls() as! Value)
            case is NSNull:
                return nil
            default:
                return $0
            
        
    

使用示例:

let dict: [String: Any] = [
    "items": ["info_editable": true,
              "name": "Android Q",
              "is_message": true,
              "images": [["id": 92,
                          "image": "/media/product/102.png"]],
              "video_description": NSNull(),
              "is_valid": true],
    "somethingElse": NSNull()
]

print(dict.strippingNulls())

样本输出:

["items": ["name": "Android Q", "info_editable": true, "images": [["image": "/media/product/102.png", "id": 92]], "is_message": true, "is_valid": true]]

【讨论】:

【参考方案4】:

试试这个。它将删除 null 并替换为空白字符串,而不会丢失密钥。

func removeNullFromResponse(response:NSDictionary) -> NSDictionary
    
    let blankString = "\"\""
    let myMutableDict: NSMutableDictionary = NSMutableDictionary(dictionary: response)

    var data = try? JSONSerialization.data(withJSONObject:myMutableDict, options: JSONSerialization.WritingOptions.prettyPrinted)

    var strData = NSString.init(data: data!, encoding:String.Encoding.utf8.rawValue)
    strData = strData?.replacingOccurrences(of: "<NULL>", with: blankString) as NSString?
    strData = strData?.replacingOccurrences(of: "<null>", with: blankString) as NSString?
    strData = strData?.replacingOccurrences(of: "<Null>", with: blankString) as NSString?
    strData = strData?.replacingOccurrences(of: "NULL", with: blankString) as NSString?
    strData = strData?.replacingOccurrences(of: "null", with: blankString) as NSString?
    
    data = strData?.data(using: String.Encoding.utf8.rawValue)!
    
    var dictionary = NSDictionary()
    
    do
    
        dictionary = try JSONSerialization.jsonObject(with: data! , options: JSONSerialization.ReadingOptions()) as! NSDictionary
        
     catch 
        print(error)
    
    
    return dictionary as NSDictionary

【讨论】:

这是一个非常不切实际的解决方案。如果任何值包含替换对象怎么办,例如Vanilla 包含 nil,该值将被替换为空白字符串并返回错误。

以上是关于swift - 从嵌套字典中删除或替换 <null> 值的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3 和 Xcode 8 中从嵌套字典中获取值的问题

从嵌套结构(带有其他结构的数组)创建字典 Swift

从嵌套字典中删除字典 [重复]

从嵌套字典中动态删除项目

递归遍历带有列表的嵌套字典,并替换匹配的值

python字典的简单操作(修改删除嵌套遍历复制)