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

Swift中如何解析首项类型不同的JSON数组并映射为指定结构体?

解析混合类型JSON数组为自定义Codable结构体的实现方案

当然可行!Swift的Codable协议本身就支持自定义解码逻辑,刚好能处理这种数组首项是Dog、其余元素都是Turtle的混合类型场景。下面我来一步步给你讲具体实现方式:

1. 定义基础结构体和目标Result结构体

首先我们需要先定义Dog、Turtle以及最终要解析成的Result结构体,它们都遵循Codable协议:

struct Dog: Codable {
    let name: String
    let breed: String
}

struct Turtle: Codable {
    let color: String
    let eats: String
}

struct Result: Codable {
    let dog: Dog
    let turtles: [Turtle]
}

2. 实现自定义解码逻辑(推荐方案)

默认的Codable解码逻辑无法直接处理这种混合类型的数组,所以我们需要给Result扩展自定义的init(from decoder: Decoder)方法。这里推荐使用UnkeyedContainer来直接遍历数组元素,这种方式更高效,不需要额外的JSON序列化转换:

extension Result {
    init(from decoder: Decoder) throws {
        // 先将整个JSON解析为一个无键容器(对应数组类型)
        let container = try decoder.singleValueContainer()
        var unkeyedContainer = try container.unkeyedContainer()
        
        // 解码第一个元素为Dog类型
        guard !unkeyedContainer.isAtEnd else {
            throw DecodingError.dataCorruptedError(in: unkeyedContainer, debugDescription: "JSON数组为空,无法解析Dog对象")
        }
        self.dog = try unkeyedContainer.decode(Dog.self)
        
        // 遍历剩余元素,解码为Turtle数组
        var turtles = [Turtle]()
        while !unkeyedContainer.isAtEnd {
            let turtle = try unkeyedContainer.decode(Turtle.self)
            turtles.append(turtle)
        }
        self.turtles = turtles
    }
}

3. 解码示例

现在我们可以用示例JSON数据来测试解码逻辑:

// 你的示例JSON字符串
let jsonString = """
[ { "name": "Spot", "breed": "dalmation" }, { "color": "green", "eats": "lettuce" }, { "color": "brown", "eats": "spinach" }, { "color": "yellow", "eats": "cucumbers" } ]
"""

do {
    let decodedResult = try JSONDecoder().decode(Result.self, from: jsonString.data(using: .utf8)!)
    print("解析成功:")
    print("Dog: \(decodedResult.dog.name) (\(decodedResult.dog.breed))")
    print("Turtles: \(decodedResult.turtles.count)只")
    decodedResult.turtles.forEach { turtle in
        print("- 颜色:\(turtle.color),食物:\(turtle.eats)")
    }
} catch {
    print("解码失败:\(error.localizedDescription)")
}

运行这段代码后,你就能得到一个包含单个Dog对象和Turtle数组的Result实例,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:07:26