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

如何解码含多类型的JSON数组?解决Decodable兼容及移除末尾Int问题

JSON混合类型数组解码问题解决:排除末尾Int或适配Decodable

为什么用AnyObject会不符合Decodable协议?

Swift的Decodable协议要求明确的类型定义,AnyObject是无类型约束的空类型,编译器无法自动推断解码规则,所以直接在struct里用AnyObject会导致无法遵守Decodable协议。


解决方案1:解码时过滤掉末尾Int,只保留字符串

通过自定义解码逻辑,先兼容混合类型的数组,再过滤出需要的字符串元素(如果确定最后一个元素是Int,也可以直接移除最后一个元素后再过滤)。

代码示例:

// 自定义枚举兼容JSON混合类型
enum JSONValue: Decodable {
    case string(String)
    case int(Int)
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let str = try? container.decode(String.self) {
            self = .string(str)
        } else if let int = try? container.decode(Int.self) {
            self = .int(int)
        } else {
            throw DecodingError.typeMismatch(
                JSONValue.self,
                DecodingError.Context(
                    codingPath: decoder.codingPath,
                    debugDescription: "不支持的JSON类型"
                )
            )
        }
    }
}

// 定义API响应结构体
struct MadLibResponse: Decodable {
    let value: [String]
    // 根据API实际返回补充其他字段,比如title、blanks等
    
    enum CodingKeys: String, CodingKey {
        case value
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 先解码成混合类型数组
        let mixedValues = try container.decode([JSONValue].self, forKey: .value)
        
        // 方式A:过滤所有字符串元素(不管Int位置)
        value = mixedValues.compactMap {
            guard case .string(let str) = $0 else { return nil }
            return str
        }
        
        // 方式B:如果确定最后一个元素是Int,先移除再过滤
        // let filteredValues = mixedValues.dropLast()
        // value = filteredValues.compactMap {
        //     guard case .string(let str) = $0 else { return nil }
        //     return str
        // }
    }
}

解决方案2:保留所有混合类型元素

如果需要保留数组里的字符串和Int,直接把value定义为[JSONValue]类型,这样结构体可以正常遵守Decodable,后续使用时再区分类型处理:

struct MadLibResponse: Decodable {
    let value: [JSONValue]
    // 其他字段...
}

// 使用时遍历区分类型
for item in response.value {
    switch item {
    case .string(let str):
        print("字符串元素:\(str)")
    case .int(let num):
        print("数字元素:\(num)")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:01:12