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

Swift中嵌套JSON转Model遇keyNotFound错误,寻求解决方案

Swift嵌套JSON解析错误解决方法

问题场景

API返回的嵌套JSON

{    
    "data": [        
        {            
            "_id": "63d9d2d57c0cfe791b2b19f6",            
            "step": {                
                "_id": "step1",                
                "status": "STARTED",                
                "children": [                    
                    {                        
                        "_id": "step2",                        
                        "status": "NOT_STARTED",                        
                        "children": [                            
                            {                                
                                "_id": "step3",                                
                                "status": "NOT_STARTED",                                
                                "children": [                                    
                                    {                                        
                                        "_id": "step3",                                        
                                        "status": "NOT_STARTED"                                    
                                    }                                
                                ]                            
                            }                        
                        ]                    
                    }                
                ]            
            },            
            "status": "IN_PROGRESS",            
            "createdBy": "2700930039"        
        }    
    ]
}

自定义的Decodable结构体

struct NestedJsonModel:Decodable {   var data:[LotData]}
struct LotData:Decodable {   var _id: String   var step: StepDetails   var status: String   var createdBy: String}
struct StepDetails:Decodable {   var _id: String   var status: String   var children: [ChildSteps]}
struct ChildSteps:Decodable {   var _id: String   var status: String   var children: [StepDetails] //because children contains the same model as Step Details}

解码代码

let jsonData = data.data(using: .utf8)!
do {    
    let decoder = JSONDecoder()    
    let tableData = try decoder.decode(NestedJsonModel.self, from: jsonData)    
    result = tableData.data    
    print("****************")    
    print(result!)    
    print("****************")
}catch {    
    print (error)
}

触发的错误信息

keyNotFound(CodingKeys(stringValue: "children", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "step", intValue: nil), CodingKeys(stringValue: "children", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "children", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"children\", intValue: nil) (\"children\").", underlyingError: nil))

错误原因

  1. 字段非必填但模型设为必填:JSON最内层的step3节点没有children字段,但StepDetails和ChildSteps中children被定义为非可选数组,解码时找不到对应key直接报错。
  2. 冗余结构体定义:StepDetails和ChildSteps字段完全一致,分开定义不仅冗余,还会导致嵌套层级匹配混乱。

解决方案

修正后的Decodable模型

方案1:将children设为可选数组

struct NestedJsonModel: Decodable {
    var data: [LotData]
}

struct LotData: Decodable {
    var _id: String
    var step: Step
    var status: String
    var createdBy: String
}

// 合并为单个递归结构体,适配嵌套层级
struct Step: Decodable {
    var _id: String
    var status: String
    var children: [Step]? // 设为可选,适配无children的节点
}

方案2:给children设置默认空数组(避免nil)

如果希望children始终为数组而非nil,可自定义解码逻辑:

struct NestedJsonModel: Decodable {
    var data: [LotData]
}

struct LotData: Decodable {
    var _id: String
    var step: Step
    var status: String
    var createdBy: String
}

struct Step: Decodable {
    var _id: String
    var status: String
    var children: [Step] = [] // 默认空数组
    
    enum CodingKeys: String, CodingKey {
        case _id, status, children
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        _id = try container.decode(String.self, forKey: ._id)
        status = try container.decode(String.self, forKey: .status)
        // 无children字段时使用默认空数组
        children = try container.decodeIfPresent([Step].self, forKey: .children) ?? []
    }
}

说明

  • 合并StepDetails和ChildSteps为Step结构体,通过递归引用自己完美匹配JSON的嵌套层级。
  • 将children设为可选或默认空数组,彻底解决无该字段时的解码报错问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 12:51:17