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

如何将JSON解码为不同类型?Swift自定义Decodable初始化报错排查

问题根源

两个核心错误直接导致报错与解码失败:

  • 容器类型选择错误:JSON单条记录为带key的对象结构,需使用keyedContainer(keyedBy:)读取对应字段,你所使用的singleValueContainer()仅适用于无结构的单值内容解析,完全不匹配当前JSON结构。
  • 初始化逻辑不完整:你编写的switch分支每次仅对3个属性中的1个赋值,剩余2个存储属性始终未完成初始化,触发了Swift编译器的存储属性初始化完整性检查,直接抛出编译错误。同时你先尝试将整个容器解码为String的逻辑,和实际JSON结构完全不符,即使编译通过运行时也会解码失败。

正确实现方案

由于JSON中的日期为自定义字符串格式,需要先配置对应格式的日期解析器,推荐以下两种实现方式:

方案1:依赖自动合成解码逻辑(无需手写init,代码量最少)

import Foundation

struct Event: Decodable & Equatable {
    let title: String
    let start: Date
    let end: Date
}

// 解码流程示例
let jsonData = 你的JSON数据变量
// 配置对应格式的日期解析器
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM dd, yyyy h:mm a"
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // 避免系统区域设置影响解析

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(dateFormatter)

do {
    let events = try decoder.decode([Event].self, from: jsonData)
    // 解析完成后可直接使用events数组
} catch {
    print("解码失败: \(error)")
}

方案2:手写自定义init(from:)实现

如果有自定义解码的业务需求,正确的解码init写法如下:

struct Event: Decodable & Equatable {
    let title: String
    let start: Date
    let end: Date
    
    enum CodingKeys: String, CodingKey {
        case title, start, end
    }
    
    init(from decoder: Decoder) throws {
        // 使用keyed容器读取所有字段
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 依次完成三个属性的解码赋值,全部赋值完成后再结束初始化流程
        self.title = try container.decode(String.self, forKey: .title)
        self.start = try container.decode(Date.self, forKey: .start)
        self.end = try container.decode(Date.self, forKey: .end)
    }
}
// 解码时的日期配置和方案1完全一致

内容的提问来源于stack exchange,提问作者Fernando Ivan Perez Ruiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:57:00