#ios #swift5 #nsjsonserialization #jsonencoder
Вопрос:
Итак, Xcode 13.1, iOS 15.0, я застрял с этой сериализацией JSON для довольно важного проекта, который должен быть доставлен вчера (!), как обычно, и вместо этого вылетает.
Это тот фрагмент кода, с которым я имею дело:
var jsonData: Data do { jsonData = try JSONSerialization.data(withJSONObject: roomBookings, options: []) } catch { print("error: ", error) return false }
Это объект, который я пытаюсь сериализовать в формате JSON:
Rooms.RoomBookings( bookings: [Rooms.RoomBooking( bookingID: "23EB86CB-A918-47D4-ADDB-346DBB4E3471", roomID: "BgX86SbN0UifijkwU8HZ", isAllDay: false, startTimestamp: 1636440856861, endTimestamp: 1636444456861, user: "trialUser") ])
Это ошибка, которую я продолжаю получать, что приводит к сбою приложения (конечно, мы можем избежать фактической проверки сбоя с помощью isValidJSONObject, но здесь дело не в этом).
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** [NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'
Вот ниже приведена модель, ошибка сосредоточена на типе верхнего уровня, что в этом плохого? Это просто набор экземпляров Roobooking, соответствующих кодируемым, и что с того?
Кто-нибудь знает, что я делаю не так? Это было бы очень ценно!
// MARK: - RoomBookings struct RoomBookings: Codable { var bookings: [RoomBooking] enum CodingKeys: String, CodingKey { case bookings = "bookings" } } // MARK: RoomBookings convenience initializers and mutators extension RoomBookings { init(data: Data) throws { self = try newJSONDecoder().decode(RoomBookings.self, from: data) } init(_ json: String, using encoding: String.Encoding = .utf8) throws { guard let data = json.data(using: encoding) else { throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil) } try self.init(data: data) } init(fromURL url: URL) throws { try self.init(data: try Data(contentsOf: url)) } func with( bookings: [RoomBooking]? = nil ) -gt; RoomBookings { return RoomBookings( bookings: bookings ?? self.bookings ) } func jsonData() throws -gt; Data { return try newJSONEncoder().encode(self) } func jsonString(encoding: String.Encoding = .utf8) throws -gt; String? { return String(data: try self.jsonData(), encoding: encoding) } } // MARK: - RoomBooking struct RoomBooking: Codable { var bookingID: String var roomID: String var isAllDay: Bool var startTimestamp: Int var endTimestamp: Int var user: String enum CodingKeys: String, CodingKey { case bookingID = "bookingId" case roomID = "roomId" case isAllDay = "isAllDay" case startTimestamp = "startTimestamp" case endTimestamp = "endTimestamp" case user = "user" } } // MARK: RoomBooking convenience initializers and mutators extension RoomBooking { init(data: Data) throws { self = try newJSONDecoder().decode(RoomBooking.self, from: data) } init(_ json: String, using encoding: String.Encoding = .utf8) throws { guard let data = json.data(using: encoding) else { throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil) } try self.init(data: data) } init(fromURL url: URL) throws { try self.init(data: try Data(contentsOf: url)) } func with( bookingID: String? = nil, roomID: String? = nil, isAllDay: Bool? = nil, startTimestamp: Int? = nil, endTimestamp: Int? = nil, user: String? = nil ) -gt; RoomBooking { return RoomBooking( bookingID: bookingID ?? self.bookingID, roomID: roomID ?? self.roomID, isAllDay: isAllDay ?? self.isAllDay, startTimestamp: startTimestamp ?? self.startTimestamp, endTimestamp: endTimestamp ?? self.endTimestamp, user: user ?? self.user ) } func jsonData() throws -gt; Data { return try newJSONEncoder().encode(self) } func jsonString(encoding: String.Encoding = .utf8) throws -gt; String? { return String(data: try self.jsonData(), encoding: encoding) } } // MARK: - Helper functions for creating encoders and decoders func newJSONDecoder() -gt; JSONDecoder { let decoder = JSONDecoder() if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) { decoder.dateDecodingStrategy = .iso8601 } return decoder } func newJSONEncoder() -gt; JSONEncoder { let encoder = JSONEncoder() if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) { encoder.dateEncodingStrategy = .iso8601 } return encoder }
Комментарии:
1. почему бы просто не использовать
try JSONEncoder().encode(roomBookings)
Ответ №1:
Попробуй
var jsonData: Data do { jsonData = try JSONEncoder().encode(roomBookings) print(String(data: data, encoding: .utf8)!) //to check the actual O/P am adding it here, remove it from your code } catch { print("error: ", error) return false }
O/P:
{ «бронирование»: [{ «Отметка времени окончания»: 1, «Идентификатор номера»: «1», «пользователь»: «abcd», «isAllDay»: true, «Идентификатор бронирования»: «1», «Отметка времени начала»: 1 }] }
Комментарии:
1. @фабрицио-проспери: Рад, что смог помочь 🙂