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

Swift中使用Codable将JSON字典解析为对象数组的实现

JSON字典转有序数组的Codable解析方案

API返回的JSON数据

{
   "someProperty":"someValue",
   "type":"type1",
   "values":{
      "first":"someValue",
      "second":"someValue"
   }
}

问题背景

原模型用[String: String]解析values可正常工作,但因为需要保留数据顺序,要改成[Value]数组结构,直接使用目标模型会报错:Expected to decode Array but found a dictionary instead.

解决方案

通过自定义Codable的解码逻辑,手动将字典转成有序数组。Swift 5.1+中,[String: String]解码时会保留JSON原有的键顺序,因此可以安全地将键值对映射为Value对象数组。

修改后的完整代码

struct MyModel: Codable {
    let someProperty: String
    let type: SomeType
    var values: [Value]?
    
    // 定义编码键
    enum CodingKeys: String, CodingKey {
        case someProperty, type, values
    }
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 解析常规字段
        someProperty = try container.decode(String.self, forKey: .someProperty)
        type = try container.decode(SomeType.self, forKey: .type)
        
        // 将字典转为Value数组
        if let valuesDict = try container.decodeIfPresent([String: String].self, forKey: .values) {
            values = valuesDict.map { Value(key: $0.key, value: $0.value) }
        } else {
            values = nil
        }
    }
    
    // 可选:如果需要将模型编码回JSON,实现此方法
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(someProperty, forKey: .someProperty)
        try container.encode(type, forKey: .type)
        
        // 将Value数组转回字典
        if let valuesArray = values {
            let valuesDict = Dictionary(uniqueKeysWithValues: valuesArray.map { ($0.key, $0.value) })
            try container.encode(valuesDict, forKey: .values)
        }
    }
}

enum SomeType: String, Codable {
    case type1, type2
}

struct Value: Codable {
    let key: String
    let value: String
}

关键说明

  1. 自定义解码:在init(from:)中,先解析someProperty和type字段,再把values解码为字典,通过map将每个键值对转为Value对象,组成数组。
  2. 顺序保留:Swift 5.1及更高版本中,Dictionary解码时会严格遵循JSON中的键顺序,因此转成数组后顺序与原JSON一致。
  3. 编码支持:如果需要将模型重新编码为JSON,实现encode(to:)方法,将[Value]数组转回[String: String]字典即可,保证和原API格式兼容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 18:56:15