迅捷可编码字典

问题描述

我在编码方面遇到了问题。任何帮助将不胜感激。我的操场上有以下物品

我的JSON文件中的样本。它具有更多元素,将其缩小为较小的子集。

{
  "Metadata" : {
    "generated" : {
      "timestamp" : 1549331723,"date" : "2019-02-04 20:55:23"
    }
  },"data" : {
    "CA" : {
      "country-id" : 25000,"country-iso" : "CA","country-eng" : "Canada","country-fra" : "Canada","date-published" : {
        "timestamp" : 1544561785,"date" : "2018-12-11 15:56:25","asp" : "2018-12-11T15:56:25.4141468-05:00"
      }
    },"BM" : {
      "country-id" : 31000,"country-iso" : "BM","country-eng" : "Bermuda","country-fra" : "Bermudes","date-published" : {
        "timestamp" : 1547226095,"date" : "2019-01-11 12:01:35","asp" : "2019-01-11T12:01:35.4748399-05:00"
      }
    }
  }
}

来自quicktype应用程序。它为Datum生成一个字典。 json的结构方式,国家/地区缩写没有标签

import Foundation

// MARK: - Welcome
struct Welcome: Codable {
    let Metadata: Metadata?
    let data: [String: Datum]?
}

// MARK: - Datum
struct Datum: Codable {
    let countryID: Int?
    let countryISO,countryEng,countryFra: String?
    let datePublished: DatePublished?

    enum CodingKeys: String,CodingKey {
        case countryID = "country-id"
        case countryISO = "country-iso"
        case countryEng = "country-eng"
        case countryFra = "country-fra"
        case datePublished = "date-published"
    }
}

// MARK: - DatePublished
struct DatePublished: Codable {
    var timestamp: Int
    var date,asp: String
}

// MARK: - Metadata
struct Metadata: Codable {
    var generated: Generated
}

// MARK: - Generated
struct Generated: Codable {
    var timestamp: Int
    var date: String
}

// MARK: - Encode/decode helpers

class JSONNull: Codable,Hashable {

    public static func == (lhs: JSONNull,rhs: JSONNull) -> Bool {
        return true
    }

    public var hashValue: Int {
        return 0
    }

    public func hash(into hasher: inout Hasher) {
        // No-op
    }

    public init() {}

    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if !container.decodeNil() {
            throw DecodingError.typeMismatch(JSONNull.self,DecodingError.Context(codingPath: decoder.codingPath,debugDescription: "Wrong type for JSONNull"))
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encodeNil()
    }
}

从我的代码中,我可以加载json文件,我不确定如何使用字典在这里处理数据,并且国家/地区没有国家/地区缩写的名称

 guard let url = Bundle.main.url(forResource: "data",withExtension: "json") else { return 0 }

        let jsonData = try Data(contentsOf: url)

注意:这是我之前的问题的后续解答:Swift Codable Parsing keyNotFound

解决方法

您的数据模型已经正确定义(但是,我建议您进行一些名称更改并从属性中删除可变性/可选性)。

一旦解析了JSON,就不必保留Dictionary,因为键实际上是country-iso键下值的一部分。

因此,一旦您解码了Root对象,我建议您简单保留root.data.values,这将为您提供Array<CountryData>,此后您可以轻松处理。

struct Root: Codable {
    let data: [String: CountryData]
}

struct CountryData: Codable {
    let countryID: Int
    let countryISO,countryEng,countryFra: String
    let datePublished: DatePublished

    enum CodingKeys: String,CodingKey {
        case countryID = "country-id"
        case countryISO = "country-iso"
        case countryEng = "country-eng"
        case countryFra = "country-fra"
        case datePublished = "date-published"
    }
}

// MARK: - DatePublished
struct DatePublished: Codable {
    let timestamp: Int
    let date,asp: String
}

do {
    let root = try JSONDecoder().decode(Root.self,from: countryJson.data(using: .utf8)!)
    let countries = root.data.values
    print(countries)
} catch {
    error
}