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

Swift如何解码OpenSky API返回的无键JSON数组为Codable自定义模型

解决方法

报错原因

Swift 默认的 Codable 自动合成逻辑会期望 StateVector 对应的 JSON 结构是键值对字典,但 OpenSky 返回的 states 数组下每个元素都是按固定顺序排布的无键数组,因此需要手动实现 StateVector 的解码逻辑,按索引读取数组元素赋值给对应属性。

另外原代码存在两处类型不匹配问题需要修正:

  • icao24 是6位十六进制字符串,并非 UUID 类型,需改为 String
  • API 部分字段可能返回 null,对应属性需要声明为可选类型

修正后的完整代码

首先修改 StateVector 结构体,添加手动解码实现:

struct FlightState: Codable {
    let time: Int
    let states: [StateVector]

    struct StateVector: Codable {
        let icao24: String
        let callsign: String?
        let origin_country: String
        let time_position: Int?
        let last_contact: Int
        let longitude: Float?
        let latitude: Float?
        let baro_altitude: Float?
        let on_ground: Bool
        let velocity: Float?
        let true_track: Float?
        let vertical_rate: Float?
        let sensors: [Int]?
        let geo_altitude: Float?
        let squawk: String?
        let spi: Bool
        let position_source: Int
        
        init(from decoder: Decoder) throws {
            // 解码为无键数组容器,按顺序读取元素
            var container = try decoder.unkeyedContainer()
            icao24 = try container.decode(String.self)
            // 呼号默认带尾部空格,这里加了trim处理,不需要可删除
            callsign = try container.decodeIfPresent(String.self)?.trimmingCharacters(in: .whitespaces)
            origin_country = try container.decode(String.self)
            time_position = try container.decodeIfPresent(Int.self)
            last_contact = try container.decode(Int.self)
            longitude = try container.decodeIfPresent(Float.self)
            latitude = try container.decodeIfPresent(Float.self)
            baro_altitude = try container.decodeIfPresent(Float.self)
            on_ground = try container.decode(Bool.self)
            velocity = try container.decodeIfPresent(Float.self)
            true_track = try container.decodeIfPresent(Float.self)
            vertical_rate = try container.decodeIfPresent(Float.self)
            sensors = try container.decodeIfPresent([Int].self)
            geo_altitude = try container.decodeIfPresent(Float.self)
            squawk = try container.decodeIfPresent(String.self)
            spi = try container.decode(Bool.self)
            position_source = try container.decode(Int.self)
        }
    }
}

原有的解码调用代码不需要修改即可正常运行:

let decoder = JSONDecoder()             
let flightState: FlightState = try! decoder.decode(FlightState.self, from: dataString.data(using: .utf8)!)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:06:00