ios - 如何在 Swift 中将字典解码为以键为值的结构

标签 ios swift xcode encoding

我需要解码像这样的字典:

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

进入 Person 结构数组:

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

我想使用 Coding 协议(protocol)实现这个映射,但很难将每个键用作结构的值。

Q: What about NSJsonSerialization?

A: I know it's quite trivial with NSJsonSerialization, but implementing it with Decodable protocol was bugging me a bit :)

最佳答案

更多的想法提醒我,在这种情况下我不需要 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 解析器。

关于ios - 如何在 Swift 中将字典解码为以键为值的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59019897/

相关文章:

iphone - MKMapView上方的IOS activityIndi​​cator subview

iphone - 如何检查触摸点是否在ios中的曲线路径的边缘上?

iphone - 如何在iOS中使用正则表达式获取匹配项?

ios - 如何格式化 UInt64.max 添加逗号

swift - 收到错误无法在属性初始值设定项中使用实例成员 'url';属性初始值设定项在 'self' 可用之前运行

ios - NSManagedObjectContext 保存但不持久化

c - 如何在 C 源代码中包含内联汇编代码?

ios - UICollectionView 全屏缩放 UICollectionViewCell

ios - 如何调试 iOS 9 扩展

ios - 从 SMS 打开应用程序,如地址打开计划或 Doctolib