处理数字字段中偶尔出现的字符串数据 JSON 的最佳方法?

Best way to handle JSON with occasional string data in numeric field?

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

这才刚刚开始发生,我正在使用的结构如下,我无法在服务器上解决这个问题,但显然不一致的数据正在崩溃 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":"NO DATA","_id":"NO DATA","lat":0,"long":0,"flag":"https://raw.githubusercontent.com/NovelCOVID/API/master/assets/flags/unknow.png"},"cases":49976,"todayCases":6242,"deaths":634,"todayDeaths":81,"recovered":368,"active":48974,"critical":1175,"casesPerOneMillion":151,"deathsPerOneMillion":2},{"country":"Spain","countryInfo":{"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,"casesPerOneMillion":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}]

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

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 可能 return "NO DATA" 因为我认为 nil 更清晰,更容易处理稍后。