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

Swift 4.1使用Codable解析JSON时无法解码嵌套数组的问题

解决Swift 4.1 Codable解析嵌套数组的问题

看起来你在手动实现GameCharacter的解码逻辑时,踩了一个常见的坑——误用了嵌套容器的方法来解析数组。我来帮你梳理清楚问题和解决方案:

问题根源

你代码里用了nestedContainer(keyedBy: Weapon.CodingKeys.self, forKey: .weapons),但这个方法是用来处理嵌套的键值对对象的,而weapons是一个数组类型,完全不需要用嵌套容器来解析,直接解码数组即可。

解决方案分两种场景

场景1:JSON中weapons直接是数组

如果你的JSON结构是这种最常见的形式(weapons字段对应一个数组):

{
  "name": "Gandalf",
  "weapons": [
    {"name": "Staff", "damage": 20},
    {"name": "Sword", "damage": 15}
  ]
}

那你只需要修改init(from:)里的weapons解析逻辑:

struct GameCharacter : Codable {
    var name : String
    var weapons : [Weapon]
    
    enum CodingKeys : String, CodingKey {
        case name
        case weapons
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        // 直接解码数组类型,这才是正确的姿势
        self.weapons = try container.decode([Weapon].self, forKey: .weapons)
    }
}

// 确保Weapon也遵循Codable(如果有自定义键可以加CodingKeys)
struct Weapon: Codable {
    var name: String
    var damage: Int
}

场景2:JSON中weapons是包含数组的嵌套对象

如果你的JSON结构是weapons字段本身是一个对象,里面才包含数组(比如下面这种):

{
  "name": "Aragorn",
  "weapons": {
    "equipped": [
      {"name": "Andúril", "damage": 30},
      {"name": "Dagger", "damage": 8}
    ]
  }
}

那你才需要用到嵌套容器,但要先定义嵌套对象的CodingKeys,再从中解码数组:

struct GameCharacter : Codable {
    var name : String
    var weapons : [Weapon]
    
    enum CodingKeys : String, CodingKey {
        case name
        case weapons
    }
    
    // 定义嵌套容器的键
    enum WeaponContainerKeys: String, CodingKey {
        case equipped
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        
        // 先获取weapons对应的嵌套键值容器
        let weaponsContainer = try container.nestedContainer(keyedBy: WeaponContainerKeys.self, forKey: .weapons)
        // 从嵌套容器里解码数组
        self.weapons = try weaponsContainer.decode([Weapon].self, forKey: .equipped)
    }
}

struct Weapon: Codable {
    var name: String
    var damage: Int
}

额外小提示

其实如果你的结构体属性名和JSON的键完全匹配,完全不需要手动实现init(from:)和CodingKeys,Codable会自动生成默认的解码逻辑,比如这样就足够:

struct GameCharacter : Codable {
    var name : String
    var weapons : [Weapon]
}

struct Weapon: Codable {
    var name: String
    var damage: Int
}

只有当你需要自定义键名、处理可选值默认值或者其他特殊逻辑时,才需要手动实现解码方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:58:58