Swift 4 Decodable:从嵌套JSON生成含Actor数组的结构体
解决方案:创建匹配JSON的PlaceholderData结构体
没问题,我来帮你搞定这个结构体定义和JSON解析的事儿。根据你给出的嵌套JSON结构,我们可以用Swift的Codable协议来优雅地处理解析,同时定义出你需要的PlaceholderData和Actor结构体。
1. 先定义Actor结构体
首先,JSON里的每个演员对象有id和name,所以先创建对应的结构体:
struct Actor: Codable { let id: Int let name: String }
2. 定义PlaceholderData结构体
因为原JSON里的演员列表嵌套在actors.nodes层级下,我们需要自定义解码逻辑来提取演员数组。这里提供两种实现方式,你可以选自己习惯的:
方式一:用中转结构体简化逻辑
这种方式通过两个私有的中转结构体来匹配JSON的嵌套结构,代码更清晰:
// 私有中转结构体,匹配JSON中的actors结构 private struct ActorsContainer: Codable { let nodes: [ActorNode] } // 私有中转结构体,匹配nodes里的单个节点 private struct ActorNode: Codable { let actor: Actor } struct PlaceholderData: Codable { let filmCount: Int let year: Int let category: String let actors: [Actor] // 自定义解码逻辑 enum CodingKeys: String, CodingKey { case filmCount, year, category, actors } init(from decoder: Decoder) throws { let rootContainer = try decoder.container(keyedBy: CodingKeys.self) // 解码基础属性 filmCount = try rootContainer.decode(Int.self, forKey: .filmCount) year = try rootContainer.decode(Int.self, forKey: .year) category = try rootContainer.decode(String.self, forKey: .category) // 解码嵌套的演员列表,中转后提取Actor数组 let actorsContainer = try rootContainer.decode(ActorsContainer.self, forKey: .actors) actors = actorsContainer.nodes.map { $0.actor } } }
方式二:直接嵌套解码(无中转结构体)
如果不想用中转结构体,也可以通过多层嵌套容器直接解码:
struct PlaceholderData: Codable { let filmCount: Int let year: Int let category: String let actors: [Actor] // 定义各层级的CodingKey enum RootKeys: String, CodingKey { case filmCount, year, category, actors } enum ActorsKeys: String, CodingKey { case nodes } enum NodeKeys: String, CodingKey { case actor } init(from decoder: Decoder) throws { let rootContainer = try decoder.container(keyedBy: RootKeys.self) // 解码基础属性 filmCount = try rootContainer.decode(Int.self, forKey: .filmCount) year = try rootContainer.decode(Int.self, forKey: .year) category = try rootContainer.decode(String.self, forKey: .category) // 逐层解析演员列表 let actorsContainer = try rootContainer.nestedContainer(keyedBy: ActorsKeys.self, forKey: .actors) var nodesArray = try actorsContainer.nestedUnkeyedContainer(forKey: .nodes) var actorsArray = [Actor]() while !nodesArray.isAtEnd { let nodeContainer = try nodesArray.nestedContainer(keyedBy: NodeKeys.self) let actor = try nodeContainer.decode(Actor.self, forKey: .actor) actorsArray.append(actor) } actors = actorsArray } }
3. 使用示例:解码JSON数据
下面是一个把JSON字符串解码成PlaceholderData的示例:
// 你的JSON字符串 let jsonString = """ { "filmCount": 5, "year": 2018, "category": "Other", "actors":{ "nodes":[ { "actor":{ "id":0, "name":"Daniel Craig" } }, { "actor":{ "id":1, "name":"Naomie Harris" } }, { "actor":{ "id":2, "name":"Rowan Atkinson" } } ] } } """ // 转换为Data对象 guard let jsonData = jsonString.data(using: .utf8) else { fatalError("Failed to convert JSON string to Data") } // 解码 do { let placeholderData = try JSONDecoder().decode(PlaceholderData.self, from: jsonData) print("Film Count: \(placeholderData.filmCount)") print("Year: \(placeholderData.year)") print("Category: \(placeholderData.category)") print("Actors: \(placeholderData.actors.map { $0.name }.joined(separator: ", "))") } catch { print("Decoding Error: \(error.localizedDescription)") }
运行这段代码,你会得到如下输出:
Film Count: 5 Year: 2018 Category: Other Actors: Daniel Craig, Naomie Harris, Rowan Atkinson
内容的提问来源于stack exchange,提问作者Brychan
相关产品推荐
相关产品推荐

