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
相关产品推荐
相关产品推荐

