Xcode 13.1与iOS 15.0环境下JSON序列化崩溃:Invalid top-level type in JSON write问题排查求助
问题根源分析
你遇到的崩溃核心原因是:JSONSerialization只能序列化Foundation框架的原生类型(比如NSDictionary、NSArray、String、Number等),而你传入的是自定义的RoomBookings结构体实例,它不属于JSONSerialization能处理的顶级类型,所以抛出了Invalid top-level type的错误。
虽然你的结构体遵循了Codable协议,但JSONSerialization和Codable是两套独立的序列化系统,不能混用。
解决方案
你有两个可行的解决方向,推荐用方案一(因为你已经实现了Codable相关的扩展):
方案一:使用你已经实现的Codable扩展来序列化
你的RoomBookings结构体已经有了jsonData()方法,直接用它替代JSONSerialization即可,这是最简洁的方式:
var jsonData: Data do { // 直接调用结构体自带的jsonData()方法 jsonData = try roomBookings.jsonData() } catch { print("error: ", error) return false }
方案二:手动将自定义类型转换为Foundation原生类型(不推荐,冗余)
如果你一定要用JSONSerialization,需要先把RoomBookings转成字典类型,不过这需要手动编写转换逻辑,不如Codable方便:
// 先把RoomBookings转成字典 let bookingDict: [String: Any] = [ "bookings": roomBookings.bookings.map { booking in [ "bookingId": booking.bookingID, "roomId": booking.roomID, "isAllDay": booking.isAllDay, "startTimestamp": booking.startTimestamp, "endTimestamp": booking.endTimestamp, "user": booking.user ] as [String: Any] } ] var jsonData: Data do { jsonData = try JSONSerialization.data(withJSONObject: bookingDict, options: []) } catch { print("error: ", error) return false }
额外说明
你提到的isValidJSONObject检查确实能避免崩溃,它的作用就是验证传入的对象是否是JSONSerialization支持的类型——显然你的RoomBookings实例会返回false,这也印证了我们的分析。
另外,你的Codable扩展已经写得很完整了,直接用它序列化/反序列化是最符合Swift现代开发习惯的方式,完全没必要再用JSONSerialization这套旧API。
内容的提问来源于stack exchange,提问作者Fabrizio Prosperi
相关产品推荐
相关产品推荐

