【问题标题】:Custom JSON Decoder自定义 JSON 解码器
【发布时间】:2022-01-14 14:09:18
【问题描述】:

json:

let json = """
[{
    "name":"abc"
    "id":"abc123"
    "university":"CMU"
},
{
    "name":"xyz"
    "id":"xyz123"
    "university":"NYU"
}]
"""

结构:

struct Student: Codable {
    let name: String
    let university: String
}

我知道我可以做得到学生名单

let students = try JSONDecoder().decode([Student].self, from: json.data(using: .utf8)!)

但我正在尝试创建一个字典,以便我可以通过学生 ID 访问任何学生。

let students = [String:Student]()
  1. 如何使用 codable 来解决这个问题?
  2. 有没有办法可以使用学生 ID 作为键和值作为学生对象?
  3. 我知道我可以运行一个循环并附加我的字典,但我正在寻找更好的解决方案。

谢谢!

【问题讨论】:

  • let dict = Dictionary(grouping: students, by: { $0.name }) ?以后就好多了……

标签: json swift dictionary decodable


【解决方案1】:

你可以使用

第 1 步:

struct Student: Codable {
    var name: String = ""
    var id: String = ""
    var university: String = ""
}

第 2 步:

let students = try JSONDecoder().decode([Student].self, from: json.data(using: .utf8)!)

 let groupedDictionary = Dictionary(grouping: students, by: 
   {String($0.id)})

【讨论】:

  • 是的,最重要的是学生词典
  • id 已经是 String。从中初始化一个新字符串是没有意义的。顺便说一句,您可以使用键路径语法let groupedDictionary = Dictionary(grouping: students, by: \.id)
  • @Saumya 是的,可以解决你要找的问题
  • @LeoDabus 是的,可以删除 String($0.id) -> $0.id
  • 非常感谢!
【解决方案2】:

您可以将 JSON 作为unkeyedContainer 解码为包装结构

let json = """
[{
    "name":"abc",
    "id":"abc123",
    "university":"CMU"
},
{
    "name":"xyz",
    "id":"xyz123",
    "university":"NYU"
}]
"""

struct Root : Decodable {
    var students = [String:Student]()
    
    init(from decoder: Decoder) throws {
        var arrayDecoder = try decoder.unkeyedContainer()
        while !arrayDecoder.isAtEnd {
            let student = try arrayDecoder.decode(Student.self)
            let id = student.id
            students[id] = student
        }
    }
}

struct Student: Decodable {
    let name, id, university: String
}

let result = try JSONDecoder().decode(Root.self, from: Data(json.utf8))
print(result.students)

【讨论】:

  • 非常感谢!
【解决方案3】:

您可以简单地为元素为 Student 的集合提供自己的下标:


extension Collection where Element == Student {
    subscript(_ id: String) -> Element? {
        first(where: {$0.id == id})
    }
}

struct Student: Codable, Hashable {
    let name: String
    let id: String
    let university: String
}

let json = """
[{
    "name":"abc",
    "id":"abc123",
    "university":"CMU"
},
{
    "name":"xyz",
    "id":"xyz123",
    "university":"NYU"
}]
"""

let students = try JSONDecoder().decode([Student].self, from: Data(json.utf8))

if let student = students["xyz123"] {
    print(student.name)         // "xyz\n"
    print(student.id)           // "xyz123\n"
    print(student.university)   // "NYU\n"
}

【讨论】:

  • 非常感谢!
猜你喜欢
  • 2017-07-27
  • 1970-01-01
  • 2012-09-06
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 2018-09-15
  • 2019-11-29
  • 2020-06-27
相关资源
最近更新 更多