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
相关产品推荐
相关产品推荐

