Swift 4解码复合物嵌套的JSON



我正在尝试创建一个清洁器代码结构,在该结构中,我只需键入day.description而不是day.weather.description

即可访问"描述">

描述值嵌套在一个仅包含一个对象的数组"天气"中。我想从索引0提取描述,并将其分配给我的结构中的描述。

这是我正在与之合作的JSON:


{
    "dt": 1558321200,
    "main": {
        "temp": 11.88,
        "temp_min": 11.88,
        "temp_max": 11.88,
        "pressure": 1013.3,
        "sea_level": 1013.3,
        "grnd_level": 1003.36,
        "humidity": 77,
        "temp_kf": 0
    },
    "weather": [{
        "id": 800,
        "main": "Clear",
        "description": "clear sky",
        "icon": "01n"
    }],
    "clouds": {
        "all": 0
    },
    "wind": {
        "speed": 5.58,
        "deg": 275.601
    },
    "sys": {
        "pod": "n"
    },
    "dt_txt": "2019-05-20 03:00:00"
}

和我到目前为止的代码:


struct Weather: Codable {
    let days: [Day]
    enum CodingKeys: String, CodingKey {
        case days = "list"
    }
}
struct Day: Codable {
    let date: String
    let main: Main
    let wind: Wind
    let description: String
    enum CodingKeys: String, CodingKey {
        case date = "dt_txt"
        case main
        case wind
        case weather
        case description
    }
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        date = try container.decode(String.self, forKey: .date)
        main = try container.decode(Main.self, forKey: .main)
        wind = try container.decode(Wind.self, forKey: .wind)
        let weather = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .weather)
        description = try weather.decode(String.self, forKey: .description)
    }
}

如您所知,最简单的方法只是一个计算的属性,它引用了所需的值。但是,为了完整,我们不妨讨论如何做您实际要求做的事情。让我们用简化版本的JSON说明:

{
  "dt": 1558321200,
  "weather": [{
    "id": 800,
    "main": "Clear",
    "description": "clear sky",
    "icon": "01n"
  }]
}

因此,问题是,我们如何将其解析为具有description属性的结构结果,从而从"weather"数组中的第一项中获取"description"键?这是一种方法:

struct Result : Decodable {
    let description : String
    enum Keys : CodingKey {
        case weather
    }
    struct Weather : Decodable {
        let description : String
    }
    init(from decoder: Decoder) throws {
        let con = try! decoder.container(keyedBy: Keys.self)
        var arr = try! con.nestedUnkeyedContainer(forKey: .weather) // weather array
        let oneWeather = try! arr.decode(Weather.self) // decode first element
        self.description = oneWeather.description
    }
}

基本上,这里的想法是nestedUnkeyedContainer给了我们数组,随后在该数组上对decode的调用会自动依次处理每个元素。我们只有一个元素,因此我们只需要一个decode调用。我们如何处理结果字符串取决于我们,因此现在我们可以将其插入我们的顶级description属性。

但这是另一种方法。我们甚至不需要二级天气结构。我们可以直接潜入"weather"数组并抓住第一个字典元素并访问其"description"键,而无需更多地谈论该内部字典中的内容,因此:

struct Result : Decodable {
    let description : String
    enum Keys : CodingKey {
        case weather
        case description
    }
    init(from decoder: Decoder) throws {
        let con = try! decoder.container(keyedBy: Keys.self)
        var arr = try! con.nestedUnkeyedContainer(forKey: .weather)
        let con2 = try! arr.nestedContainer(keyedBy: Keys.self)
        let desc = try! con2.decode(String.self, forKey: .description)
        self.description = desc
    }
}

您的问题不是很完整(您没有显示您的 Real JSON,只是摘录(,所以我不能提供任何精确的建议,但是我敢肯定您可以看到

如何适应此技术。

相关内容

  • 没有找到相关文章

最新更新