首页 > 解决方案 > 处理带有数字字段中偶尔字符串数据的 JSON 的最佳方法?

问题描述

我想知道是否有人可以帮助我以最佳方式处理应该是数字但偶尔显示为字符串的类型。

在此处输入图像描述

这才刚刚开始发生,我正在使用的结构在下面,我无法在服务器上解决这个问题,但显然不一致的数据正在崩溃 JSONDecoder

struct CountryInfo: Codable {
    var iso2: String
    var iso3: String
    var _id: Int
    var lat: Double
    var long: Double
    var flag: String
}

任何帮助将非常感激。

编辑:sample.json 添加

注意在中国 _id = 156 但在伊朗 _id = "NO DATA"

[{"country":"China","countryInfo":{"iso2":"CN","iso3":"CHN","_id":156,"lat":35,"long":105," flag":" https://raw.githubusercontent.com/NovelCOVID/API/master/assets/flags/cn.png "},"cases":81171,"todayCases":78,"deaths":3277,"todayDeaths ":7,"recovered":73159,"active":4735,"critical":1573,"casesPerOneMillion":56,"deathsPerOneMillion":2},{"country":"Italy","countryInfo":{" iso2":"IT","iso3":"ITA","_id":380,"lat":42.8333,"long":12.8333,"flag":" https://raw.githubusercontent.com/NovelCOVID/API/master/assets/flags/it.png "},"cases":69176,"todayCases":5249,"deaths":6820,"todayDeaths":743,"recovered":8326,"active ":54030,"critical":3393,"casesPerOneMillion":1144,"deathsPerOneMillion":113},{"country":"USA","countryInfo":{"iso2":"NO DATA","iso3": "没有数据","_id":"没有数据","lat":0,"long":0,"flag":"country":"USA","countryInfo":{"iso2":"NO DATA","iso3":"NO DATA","_id":"NO DATA","lat":0,"long":0 ,“旗帜”:”country":"USA","countryInfo":{"iso2":"NO DATA","iso3":"NO DATA","_id":"NO DATA","lat":0,"long":0 ,“旗帜”:”https://raw.githubusercontent.com/NovelCOVID/API/master/assets/flags/unknow.png "},"cases":49976,"todayCases":6242,"deaths":634,"todayDeaths":81, “恢复”:368,“活跃”:48974,“关键”:1175,“casesPerOneMillion”:151,“deathsPerOneMillion”:2},{“国家”:“西班牙”,“国家信息”:{“iso2”:” ES","iso3":"ESP","_id":724,"lat":40,"long":-4,"flag":" https://raw.githubusercontent.com/NovelCOVID/API/master /assets/flags/es.png "},"cases":39676,"todayCases":4540,"deaths":2800,"todayDeaths":489,"recovered":3794,"active":33082,"critical" :2355,"casePerOneMillion":849,"deathsPerOneMillion":60},{"country":"Germany","countryInfo":{"iso2":"DE","iso3":"DEU","_id":276,"lat ":51,"long":9,"flag":" https://raw.githubusercontent.com/NovelCOVID/API/master/assets/flags/de.png"},"cases":32781,"todayCases":3725,"deaths":156,"todayDeaths":33,"recovered":3133,"active":29492,"critical":23,"casesPerOneMillion":391 ,"deathsPerOneMillion":2},{"country":"Iran","countryInfo":{"iso2":"NO DATA","iso3":"NO DATA","_id":"NO DATA"," lat":0,"long":0,"flag":" https://raw.githubusercontent.com/NovelCOVID/API/master/assets/flags/unknow.png "},"cases":24811,"todayCases ":1762,"deaths":1934,"todayDeaths":122,"recovered":8913,"active":13964,"critical":0,"casesPerOneMillion":295,"deathsPerOneMillion":23}]

标签: jsonswiftcodablejsondecoder

解决方案


您可以编写一个自定义init(from),在其中尝试解码 _id 使用try?以使结果可选,这意味着您需要将属性的声明更改为可选

struct Country: Decodable {
    let country: String
    let countryInfo: CountryInfo
}
struct CountryInfo: Decodable {
    var iso2: String
    var iso3: String
    var id: Int?
    var lat: Double
    var long: Double
    var flag: String

    enum CodingKeys: String, CodingKey {
        case iso2, iso3
        case id = "_id"
        case lat, long, flag
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        iso2 = try container.decode(String.self, forKey: .iso2)
        iso3 = try container.decode(String.self, forKey: .iso3)
        id = try? container.decode(Int.self, forKey: .id)
        lat = try container.decode(Double.self, forKey: .lat)
        long = try container.decode(Double.self, forKey: .long)
        flag = try container.decode(String.self, forKey: .flag)
    }
}

我还会选择在 API 可能返回“NO DATA”的情况下将任何属性设为可选,因为我认为nil以后会更清晰、更容易处理。


推荐阅读