簡體   English   中英

如何在 Swift 中以鍵為值將字典解碼為結構體

[英]How to decode a dictionary into struct with key as a value in Swift

我需要解碼一個字典,如:

{
  "Bob": "London",
  "Alice": "Berlin"
  ...
}

進入Person結構數組:

struct Person {
  let name: String
  let city: String
}

我想使用Coding協議來實現這個映射,但很難將每個鍵用作結構的值。

問: NSJsonSerialization怎么樣?

答:我知道NSJsonSerialization很簡單,但是用Decodable協議實現它讓我有點Decodable :)

更多的想法提醒我在這種情況下我不需要 AnyCodingKey 因為這是一個如此簡單的結構。 解碼為[String: String] ,然后進行映射:

struct PersonList: Decodable {
    let persons: [Person]

init(from decoder: Decoder) throws {
    self.persons = try decoder.singleValueContainer()
        .decode([String: String].self)
        .map(Person.init)
    }
}

let list = try JSONDecoder().decode(PersonList.self, from: json).persons

// [Person(name: "Bob", city: "London"), Person(name: "Alice", city: "Berlin")]

舊答案,因為有時這種技術很方便。

對此的關鍵工具是經常需要的 CodingKey(它確實應該在 stdlib 中),AnyCodingKey:

struct AnyCodingKey: CodingKey {
    var stringValue: String = ""
    init?(stringValue: String) { self.stringValue = stringValue }
    var intValue: Int?
    init?(intValue: Int) { self.intValue = intValue }
}

有了這個,你只需要一個容器來掛解碼器。 稱之為 PersonList:

struct PersonList: Decodable {
    let persons: [Person]

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: AnyCodingKey.self)
        self.persons = try container.allKeys.map { key in
            Person(name: key.stringValue,
                   city: try container.decode(String.self, forKey: key))
        }
    }
}

let list = try JSONDecoder().decode(PersonList.self, from: json).persons

// [Person(name: "Bob", city: "London"), Person(name: "Alice", city: "Berlin")]

這只是將每個鍵/值映射到一個人。

請記住,JSON 對象沒有排序,因此結果數組的順序可能與 JSON 不同,如本示例中所示。 這無法通過 Foundation(JSONSerialization 或 JSONDecoder)修復; 如果需要,您必須使用不同的 JSON 解析器。

在這種情況下,我希望使用傳統的JSONSerialization ,返回的字典可以輕松地映射到Person數組

let json = """
{
  "Bob": "London",
  "Alice": "Berlin"
}
"""

struct Person {
  let name: String
  let city: String
}

do {
    if let dataDictionary = try JSONSerialization.jsonObject(with: Data(json.utf8)) as? [String:String] {
        let people = dataDictionary.map{Person(name: $0.key, city: $0.value)}
        print(people)
    }
} catch {
    print(error)
}

暫無
暫無

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

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