【问题标题】:How to ignore nil json values in codable如何在可编码中忽略 nil json 值
【发布时间】:2019-08-18 22:56:08
【问题描述】:

我目前收到了Auto-RenewableNon-Renewable 的收据。但是Non-Renewable 不会以expires_date json 键返回。我怎么能忽略这一点。我试图避免将expires_date 设为可选。当我将其设为可选时,Apple 会发回响应。有没有办法可以在不使expires_date 可选的情况下解码json。

struct Receipt: Codable {

    let expiresDate: String

    private enum CodingKeys: String, CodingKey {
        case expiresDate = "expires_date"
    }
}

现在我可以得到

"没有与键 CodingKeys 关联的值(stringValue: \"expires_date\", intValue: nil) (\"expires_date\")。"

【问题讨论】:

  • without making expires_date optional 那么如果 JSON 包含 nil ,您期望该字段的值是什么?
  • Auto_renewable 收据包含 expires_dateNon Renewable 不包含。苹果在那里检查所有的 json 并拒绝发送响应。当我将它设为可选时,它适用于Auto_renewable,但适用于Non Renewable。由于我将SwiftStoreKit 用于Non-Renewable,因此它会检查收据和崩溃,说expires_date 为零。
  • @Dharmesh 那是我不想做并试图避免的事情

标签: ios json swift codable


【解决方案1】:

在将 nil 合并为默认值之前,您必须实现自己的 init(from: Decoder) 并使用 decodeIfPresent(_:forKey:)

struct Receipt: Codable {
    let expiresDate: String
    
    enum CodingKeys: String, CodingKey {
        case expiresDate = "expires_date"
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)        
        self.expiresDate = try values.decodeIfPresent(String.self, forKey: .expiresDate)
            ?? "1970" //Default value
    }        
}

注意:

  • 如果Receipt 有更多的键值对,那么您也必须手动解码。

使用示例:

let data = """
[{
  "expires_date": "2019"
},
{

}]
""".data(using: .utf8)!

do {
    let obj = try JSONDecoder().decode([Receipt].self, from: data)
    print(obj)
}
catch {
    print(error)
}

【讨论】:

    【解决方案2】:

    手动解码怎么样:

    struct Receipt: Codable {
    
        let expiresDate: String
    
        private enum CodingKeys: String, CodingKey {
            case expiresDate = "expires_date"
        }
    
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            if let expDate = try? values.decode(String.self, forKey: .expiresDate) {
                self.expiresDate = expDate
            } else {
                self.expiresDate = "sth"
            }
        }
    }
    

    例子:

    struct Receipt: Codable {
    
        let expiresDate: String
        let b: String
    
        private enum CodingKeys: String, CodingKey {
            case expiresDate = "expires_date"
            case b = "b"
        }
    
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            if let expDate = try? values.decode(String.self, forKey: .expiresDate) {
                self.expiresDate = expDate
            } else {
                self.expiresDate = "sth"
            }
            b = try values.decode(String.self, forKey: .b)
        }
    }
    
    
    let a = """
    {
        "b": "asdf"
    }
    """.data(using: .utf8)!
    let myStruct = try JSONDecoder().decode(Receipt.self, from: a)
    print(myStruct) //Receipt(expiresDate: "sth", b: "asdf")
    

    【讨论】:

    • 我之前厌倦了这个,它让我的不可更新的说 expiryDate 是 nil 崩溃
    • 嗯?为什么是零?如果无法解析密钥“expires_date”,我将其设置为“sth”,再试一次,它应该可以工作,但请确保所有其他密钥都是正确的
    猜你喜欢
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多