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

Swift中JSONSerialization.data处理含Codable结构体的字典崩溃如何解决

崩溃原因

JSONSerialization仅支持NSString、NSNumber、NSArray、NSDictionary、NSNull这几类可桥接到Foundation的基础类型,你直接将Swift自定义的Department结构体放入字典时,JSONSerialization无法识别该类型,就会抛出Invalid type in JSON write (__SwiftValue)错误。

可行方案

你不想手动构造Person对象的前提下,有两种可靠实现方式:


方案1:通用Encodable转字典,适配JSONSerialization

给Encodable加扩展实现自动转Foundation兼容字典,不需要你手动拼接自定义类型的属性:

extension Encodable {
    func toDictionary() throws -> [String: Any] {
        let data = try JSONEncoder().encode(self)
        let jsonObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
        guard let dict = jsonObject as? [String: Any] else {
            throw NSError(domain: "EncodableError", code: -1, userInfo: [NSLocalizedDescriptionKey: "类型转换失败"])
        }
        return dict
    }
}

改造原有代码,先把自定义类型转成字典再放入参数字典:

// 把Department数组转成JSONSerialization可识别的字典数组
let deptDicts = try [Department(bb: "D")].map { try $0.toDictionary() }
let dict = ["a": "aa", "b": deptDicts] as [String : Any]
// 现在可正常调用JSONSerialization
let data = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)

方案2:直接用JSONEncoder编码(优先推荐)

Swift原生的JSONEncoder是专门为Codable类型设计的编解码工具,不需要你手动处理任何属性映射,代码更简洁:

// 直接构造Person,编译器自动生成成员构造器,无需手动做额外映射
let person = Person(a: "aa", b: [Department(bb: "D")])
// 配置格式化输出
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
// 直接编码得到目标Data
let data = try? encoder.encode(person)

该方案性能和兼容性都优于JSONSerialization,不需要额外做类型转换,更适配Swift开发场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:24:03