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

使用Swift 4 Decodable解析含混合属性值的JSON

嘿,这个场景我太熟悉了——JSON里的字段类型不固定确实是Swift Decodable的一个小坎儿,不过咱们用枚举就能完美解决!

核心思路:用枚举封装多类型值

因为你的fields对象里的子值可能是字符串、整数或者自定义对象,我们可以先定义一个遵循Decodable的枚举,把所有可能的类型都包含进去,然后在解码的时候自动匹配对应的类型。

步骤1:定义嵌套对象(如果有需要的话)

如果fields里的子对象有固定结构,先把它的结构体写出来:

struct NestedFieldObject: Decodable {
    let subKey: String
    let subValue: Int
    // 这里根据你实际的JSON结构添加属性
}

步骤2:定义处理多类型的枚举

这个枚举会负责解码字符串、整数和自定义对象:

enum FieldValue: Decodable {
    case string(String)
    case int(Int)
    case nestedObject(NestedFieldObject)
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        
        // 按顺序尝试解码不同类型,成功就赋值对应case
        if let strValue = try? container.decode(String.self) {
            self = .string(strValue)
            return
        }
        
        if let intValue = try? container.decode(Int.self) {
            self = .int(intValue)
            return
        }
        
        if let objValue = try? container.decode(NestedFieldObject.self) {
            self = .nestedObject(objValue)
            return
        }
        
        // 如果所有类型都匹配失败,抛出解码错误
        throw DecodingError.dataCorruptedError(
            in: container,
            debugDescription: "无法识别的字段值类型"
        )
    }
}

步骤3:定义主响应结构体

把id、key和fields(类型为[String: FieldValue])都包含进来:

struct APIResponse: Decodable {
    let id: String
    let key: String
    let fields: [String: FieldValue]
}

步骤4:解码并使用数据

现在就可以正常解码JSON数据了,之后通过switch枚举值来处理不同类型的字段:

// 假设你已经拿到了JSON数据jsonData
do {
    let response = try JSONDecoder().decode(APIResponse.self, from: jsonData)
    
    // 遍历fields处理每个字段
    for (fieldName, fieldValue) in response.fields {
        switch fieldValue {
        case .string(let str):
            print("\(fieldName): 字符串 -> \(str)")
        case .int(let num):
            print("\(fieldName): 整数 -> \(num)")
        case .nestedObject(let obj):
            print("\(fieldName): 嵌套对象 -> 子键:\(obj.subKey),子值:\(obj.subValue)")
        }
    }
} catch {
    print("解码出错:\(error.localizedDescription)")
}

扩展说明

  • 如果fields里还有其他类型(比如布尔值、数组),只需要给枚举添加对应的case,然后在init(from:)里多加一个解码分支就行。
  • 如果某些字段可能为null,可以添加.null的case,并在解码时尝试container.decodeNil()来处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:53:31