You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:33:33