如何忽略可编码的nil json值

时间:2019-03-28 08:28:28

标签: ios json swift codable

我目前退回Auto-RenewableNon-Renewable的收据。但是Non-Renewable并没有返回expires_date json键。我怎么能忽略这一点。我试图避免将expires_date设为可选。当我将其设置为可选时,Apple会发送回响应。有没有办法我可以解码json而无需将expires_date设为可选。

struct Receipt: Codable {

    let expiresDate: String

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

现在我可以得到

  
    

“没有与键CodingKeys相关联的值(字符串值:\“ expires_date \”,整数值:nil)(\“ expires_date \”)。“

  

2 个答案:

答案 0 :(得分:4)

您将必须实现自己的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)
}

答案 1 :(得分:3)

如何对其进行手动解码:

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")