簡體   English   中英

Swift 4解碼復雜的嵌套JSON

[英]Swift 4 decode complex nested JSON

我正在嘗試創建一個更清晰的可編碼結構,我可以通過輸入day.description而不是day.weather.description來訪問“描述”。

描述值嵌套在一個只包含單個對象的數組“weather”中。 我想從索引0中提取描述並將其分配給我的struct中的描述。

這是我正在使用的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屬性的struct Result,以便我們從"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結構; 我們可以直接進入"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
    }
}

你的問題不是很完整(你沒有展示你真正的 JSON,只是一個摘錄),所以我不能給出更精確的建議,但我相信你能看到這種技術如何適應你的需求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM