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

Swift使用Codable解码JSON时自定义对象键缺失的处理方法

Swift Codable 解析缺失键的实现方案

问题场景

解析JSON时存在部分可选键可能缺失的情况,完整JSON结构示例如下:

{
  "data": "some text",
  "id": "3213",
  "title": "title",
  "description": "description",
  "customObj1": [{
      "id": "2423",
      "count": 35
      // 其余自定义字段
    }],
  "customObj2": [{
      "number": "2423",
      "name": "john"
      // 其余自定义字段
    }],
  "customObj3": [{
      "like": "2423",
      "Other": 9
      // 其余自定义字段
    }]
}

其中customObj1、customObj2、customObj3三个字段可能不存在于返回结果中,需要基于Codable协议用struct实现兼容解析。原有未完成的模型代码存在两个问题:一是可选字段没有声明为可选类型,二是自定义decoder初始化逻辑未补全。


实现方法

方法1:最简实现(无需手写init方法)

Codable协议默认会对可选类型属性做键缺失兼容:如果键不存在,会自动赋值为nil,不需要手动写判断逻辑,只需要把可能缺失的字段声明为可选类型即可。
修正后的完整模型代码:

// MARK: - Response
struct Response: Codable {
    let data, id, title: String
    // 遵循Swift小驼峰命名规范,无需大写开头
    let description: String
    // 可能缺失的字段声明为可选数组类型
    let customObj1: [CustomObj1]?
    let customObj2: [CustomObj2]?
    let customObj3: [CustomObj3]?

    enum CodingKeys: String, CodingKey {
        case data, id, title, description
        case customObj1, customObj2, customObj3
    }
}

// MARK: - CustomObj1
struct CustomObj1: Codable {
    let id: String
    let count: Int
}

// MARK: - CustomObj2
struct CustomObj2: Codable {
    let number, name: String
}

// MARK: - CustomObj3
struct CustomObj3: Codable {
    let like: String
    let other: Int

    enum CodingKeys: String, CodingKey {
        case like
        case other = "Other"
    }
}

补充:如果希望键不存在时默认返回空数组而不是nil,可以给属性加默认值[],同时声明为非可选类型,例如let customObj1: [CustomObj1] = [],Codable也会自动处理缺失键的情况。


方法2:自定义init(from decoder:) 实现

如果需要在解码时做额外逻辑处理,可以手动实现初始化方法,核心是用decodeIfPresent方法解析可选字段,补全后的代码如下:

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    // 必传字段直接用decode解析,键缺失会直接抛出解码错误
    data = try values.decode(String.self, forKey: .data)
    id = try values.decode(String.self, forKey: .id)
    title = try values.decode(String.self, forKey: .title)
    description = try values.decode(String.self, forKey: .description)
    
    // 可选字段用decodeIfPresent解析,键不存在时自动返回nil
    customObj1 = try values.decodeIfPresent([CustomObj1].self, forKey: .customObj1)
    customObj2 = try values.decodeIfPresent([CustomObj2].self, forKey: .customObj2)
    customObj3 = try values.decodeIfPresent([CustomObj3].self, forKey: .customObj3)
    
    // 原有代码里的self.category是笔误,替换成对应字段即可
    // 如果需要自定义默认值,也可以在这里处理,例如:
    // customObj1 = try values.decodeIfPresent([CustomObj1].self, forKey: .customObj1) ?? []
}

如果要手动判断键是否存在再处理,写法如下:

if values.contains(.customObj1) {
    customObj1 = try values.decode([CustomObj1].self, forKey: .customObj1)
} else {
    customObj1 = nil
}

这种写法和decodeIfPresent效果完全一致,更推荐直接用decodeIfPresent,代码更简洁。


注意事项

  • 按照Swift命名规范,属性名建议使用小驼峰,原有代码里的ResponseDescription大写开头不符合规范,直接命名为description即可,因为该名称和JSON键名一致,不需要额外在CodingKeys里做映射。
  • 如果希望字段缺失时不返回nil而是返回空数组,直接给属性设置默认值[],或者在自定义init里用空合取运算符??做兜底即可。
  • 不要混用非可选类型和缺失键场景:如果属性声明为非可选的[CustomObj1],JSON里缺省对应键时Codable会直接抛出解码错误,必须声明为可选或者设置默认值才能兼容缺省情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:27:25