Как игнорировать значения nil json в кодируемом - PullRequest
2 голосов
/ 28 марта 2019

В настоящее время я получаю квитанции как Auto-Renewable, так и Non-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 (stringValue: \" expires_date \ ", intValue: nil) (\"expires_date \ ")."

Ответы [ 2 ]

4 голосов
/ 28 марта 2019

Вам придется реализовать свой собственный init(from: Decoder) и использовать decodeIfPresent(_:forKey:) до слияния nil до значения по умолчанию.

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)
}
3 голосов
/ 28 марта 2019

Как насчет ручного декодирования:

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