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

Swift解码混合类型JSON数组:如何避免使用双迭代器?

优化异构JSON数组的Swift解码实现

你当前的实现使用了两个unkeyedContainer分别完成类型判断和解码操作,存在遍历冗余,还可能因容器不同步引发潜在问题。以下是更简洁高效的优化方案,仅通过一次遍历完成所有逻辑:

import Foundation

struct JSONArray: Decodable {
    let a: [A]
    let b: [B]

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()
        
        var aArray: [A] = []
        var bArray: [B] = []
        
        while !container.isAtEnd {
            // 通过嵌套容器判断当前元素的类型
            let nestedContainer = try container.nestedContainer(keyedBy: CodingKeys.self)
            
            if nestedContainer.contains(.a) {
                // 直接从当前容器解码A类型元素
                let item = try container.decode(A.self)
                aArray.append(item)
            } else if nestedContainer.contains(.b) {
                // 直接从当前容器解码B类型元素
                let item = try container.decode(B.self)
                bArray.append(item)
            } else {
                // 可选:处理未知类型元素,避免解码失败
                _ = try container.decode(UnknownElement.self)
            }
        }
        
        a = aArray
        b = bArray
    }

    private enum CodingKeys: String, CodingKey {
        case a, b
    }
    
    // 用于跳过未知类型元素的空结构体
    private struct UnknownElement: Decodable {}
}

struct A: Decodable {
    let a: String
}

struct B: Decodable {
    let b: String
}

// 测试代码
let json = """
[
    {
        "a": "abc"
    },
    {
        "a": "def"
    },
    {
        "b": "def"
    },
    {
        "c": "ignore"
    }
]
"""

guard let data = json.data(using: .utf8) else { fatalError() }
do {
    let decoded = try JSONDecoder().decode(JSONArray.self, from: data)
    print("A数组: \(decoded.a)")
    print("B数组: \(decoded.b)")
} catch {
    print("解码失败: \(error)")
}

核心优化点

  • 单次遍历:仅用一个unkeyedContainer完成类型判断与解码,消除冗余遍历
  • 状态可靠:无需维护两个容器的同步状态,避免因容器偏移导致的解码错误
  • 扩展性强:新增类型时只需在判断分支中添加对应解码逻辑,未知类型可统一跳过或抛出错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 04:56:34