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

Swift中如何解码双层嵌套数组结构的JSON?

解决双层嵌套JSON到自定义结构体的解码问题

没问题,我来帮你搞定这个双层嵌套的JSON解码需求!我们可以通过自定义init(from:)解码器来处理这种非直接匹配的JSON结构,下面是具体的实现步骤和代码:

第一步:定义基础结构体

首先我们需要定义Dog结构体,它很直接,只需要遵循Codable协议即可:

struct Dog: Codable {
    let name: String
}

第二步:为Result实现自定义解码器

核心就是给Result结构体编写自定义的初始化方法,来手动处理JSON的双层嵌套逻辑:

struct Result: Codable {
    let dogs1: [Dog]
    let dogs2: [Dog]
    
    // 自定义解码初始化器
    init(from decoder: Decoder) throws {
        // 根节点是数组,所以先创建一个无键容器(UnkeyedContainer)
        var unkeyedContainer = try decoder.unkeyedContainer()
        
        // 处理第一个数组元素:取出data -> children
        let firstItemContainer = try unkeyedContainer.nestedContainer(keyedBy: CodingKeys.self)
        let firstDataContainer = try firstItemContainer.nestedContainer(keyedBy: DataCodingKeys.self, forKey: .data)
        self.dogs1 = try firstDataContainer.decode([Dog].self, forKey: .children)
        
        // 处理第二个数组元素:同样取出data -> children
        let secondItemContainer = try unkeyedContainer.nestedContainer(keyedBy: CodingKeys.self)
        let secondDataContainer = try secondItemContainer.nestedContainer(keyedBy: DataCodingKeys.self, forKey: .data)
        self.dogs2 = try secondDataContainer.decode([Dog].self, forKey: .children)
        
        // 额外校验:如果数组元素超过2个,抛出错误(可选,根据你的需求调整)
        if !unkeyedContainer.isAtEnd {
            throw DecodingError.dataCorruptedError(in: unkeyedContainer, debugDescription: "JSON数组包含超过2个元素,不符合预期结构")
        }
    }
    
    // 用于解码外层对象的键
    private enum CodingKeys: String, CodingKey {
        case data
    }
    
    // 用于解码data内部的键
    private enum DataCodingKeys: String, CodingKey {
        case children
    }
}

第三步:测试解码逻辑

你可以用下面的代码来验证解码是否正常工作:

// 你的原始JSON数据
let jsonString = """
[
    {
        "data": {
            "children": [
                {"name": "Ralph"},
                {"name": "Woofer"}
            ]
        }
    },
    {
        "data": {
            "children": [
                {"name": "Spot"},
                {"name": "Trevor"}
            ]
        }
    }
]
"""

// 尝试解码
do {
    let data = jsonString.data(using: .utf8)!
    let result = try JSONDecoder().decode(Result.self, from: data)
    print("Dogs1: \(result.dogs1.map(\.name))") // 输出:Dogs1: ["Ralph", "Woofer"]
    print("Dogs2: \(result.dogs2.map(\.name))") // 输出:Dogs2: ["Spot", "Trevor"]
} catch {
    print("解码失败:\(error)")
}

关键逻辑解释

  1. 无键容器(UnkeyedContainer):因为JSON的根节点是数组,所以我们用unkeyedContainer()来遍历数组中的每个元素。
  2. 嵌套容器:对于数组里的每个对象,我们先取出data对应的容器,再从data容器里取出children对应的[Dog]数组。
  3. 错误处理:加入了数组元素数量的校验,确保JSON结构符合预期,避免后续出现意外问题(你可以根据实际需求调整或移除这部分)。

内容的提问来源于stack exchange,提问作者Doug Smith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:16:40