解码JSON中的可选值-Swift 4

时间:2019-01-22 15:54:33

标签: swift optional jsondecoder

我已经阅读了很多教程,并在SO上搜索了答案;

Decoding Nested JSON with Optional Values Swift 4

Swift 4 Not decoding JSON optional properly

使用以下代码解码可选对象似乎没有问题。显然我在做错事,但这是什么!?

部分代码:

struct ProductInfo: Codable {
    var name: String?
    let images: [Image]
    var ingredients: String?
    let origin: [Origin]
    let producer: Producer

    enum CodingKeys: String, CodingKey {
        case name = "Artikelbenamning"
        case images = "Bilder"
        case ingredients = "Ingrediensforteckning"
        case origin = "Tillverkningslander"
        case producer = "Varumarke"
    }

    init(from decoder: Decoder) throws {

        let values = try decoder.container(keyedBy: CodingKeys.self)

        name = try? values.decodeIfPresent(String.self, forKey: .name)!
        images = try values.decodeIfPresent([Image].self, forKey: .images)!
        ingredients = try? values.decodeIfPresent(String.self, forKey: .ingredients)!
        origin = try values.decodeIfPresent([Origin].self, forKey: .origin)!
        producer = try values.decodeIfPresent(Producer.self, forKey: .producer)!
    }
}

该应用程序查询产品数据库。商品不存在时,返回以下json。

尝试在init(from :)中解码nil名称(“ json中的Artikelbenamning”)时,应用崩溃。

{
    "GTIN": null,
    "TillverkarensArtikelnummer": null,
    "Artikelbenamning": null,
    "RegleratProduktnamn": null,
    "Forvaringsinstruktion": null,
    "Variabelmattsindikator": false,
    "Bruttovikt": null,
    "Bredd": null,
    "Djup": null,
    "Hojd": null,
    "Returemballage": false,
    "FarligtGodsKod": null,
    "FarligtGodsKlass": null,
    "FarligtGodsForpackningsgrupp": null,
    "GPCKod": null,
    "GiltigFROM": null,
    "Publiceringsdatum": null,
    "FakturerbarEnhet": false,
    "Slutdatum": null,
    "GiltighetsdatumPris": null,
    "Tillganglighetstidpunkt": null,
    "SistaTillganglighetstidpunkt": null,
    "SkapadDatum": null,
    "SenastAndradDatum": null,
    "Flampunkt": null,
    "KodBegransadMangd": null,
    "OfficiellTransportbenamning": null,
    "OspecificeradTransportbenamning": null,
    "TunnelrestriktionADR": null,
    "KlassificeringskodFarligtgods": null,
    "Transportkategori": null,
    "Konsumentartikel": false,
    "BestallningsbarForpackning": false,
    "RabattOlaglig": null,
    "Garantiloptid": 0,
    "Konsumentdatum": null,
    "Tjanst": false,
    "Sasongsindikator": null,
    "Engangskop": null,
    "AntalReturnerbaraEnheter": 0,
    "Staplingsriktning": null,
    "Staplingstyp": null,
    "MaxTransportTemperatur": 0.0,
    "MinTransportTemperatur": 0.0,
    "Anvandningsinstruktioner": null,
    "HallbarhetEfterOppning": 0,
    "Riskfras": null,
    "KodlistutgivareRiskfras": null,
    "Klassificeringssystem": null,
    "FarligtGodsBegransadMangd": null,
    "FarligtGodsOvrigInfo": null,
    "FarligtGodsSarbestammelser": null,
    "T3495_Artikelavisering": null,
    "T4032_TypAvUtgangsdatum": null,
    "T3742_ForstaLeveransdatum": null,
    "Undervarumarke": null,
    "Niva": null,
    "Produktbladslank": null,
    "KompletterandeProduktklass": null,
    "T4200_AllmänPubliceringstidpunkt": null,
    "T3848_TypAvTryckkanslighet": null,
    "Varningsetiketter": [],
    "Sasongskoder": [],
    "Produktklasser": [],
    "MaskinellMarkningar": [],
    "Bilder": [],
    "ReferenserTillAndraArtiklar": [],
    "MSRKritierier": [],
    "Kravspecifikationer": [],
    "Receptlinks": [],
    "Allergener": [],
    "Markningar": [],
    "Ingredienser": [],
    "Tillagningsinformation": [],
    "Tillverkningslander": [],
    "Naringsinfo": [],
    "Serveringsforslag": [],
    "Diettyper": [],
    "Tillagningsmetoder": [],
    "Farger": [],
    "VillkorForsaljning": [],
    "Varumarke": {
        "Varumarke": null,
        "AgareGLN": null,
        "AgareNamn": null,
        "Tillverkare": {
            "Namn": null,
            "EAN": null
        }
    },
    "Nettoinnehall": [],
    "Kontakter": [],
    "Faroangivelser": [],
    "Sakerhet": [],
    "Forpackningar": [],
    "Tillsatser": [],
    "Substanser": [],
    "Fangstzoner": [],
    "Marknadsbudskap": null,
    "KortMarknadsbudskap": null,
    "Komponenter": null
}

1 个答案:

答案 0 :(得分:0)

在这种情况下,API decodeIfPresent毫无意义,因为存在密钥

具有null值的 existing 键和 missing 键是两种不同的情况。

也不要在init(from decoder方法中强行打开包装。

有两种选择:

  1. 删除整个init方法,然后可选的struct成员处理null值。
  2. 使用常规decode并忽略该错误

    name = try? values.decode(String.self, forKey: .name)