Как сериализовать или преобразовать объекты Swift в JSON?

Этот ниже class

class User: NSManagedObject { @NSManaged var id: Int @NSManaged var name: String } 

Необходимо преобразовать в

 { "id" : 98, "name" : "Jon Doe" } 

Я попытался вручную передать объект функции, которая устанавливает переменные в словарь и возвращает словарь. Но я хотел бы получить лучший способ добиться этого.

В быстром 4 вы можете наследовать от типа Codable .

 struct Dog: Codable { var name: String var owner: String } // Encode let dog = Dog(name: "Rex", owner: "Etgar") let jsonEncoder = JSONEncoder() let jsonData = try jsonEncoder.encode(dog) let json = String(data: jsonData, encoding: String.Encoding.utf16) // Decode let jsonDecoder = JSONDecoder() let dog = try jsonDecoder.decode(Dog.self, from: jsonData) 

EVReflection :

  • Это работает принцип отражения. Это занимает меньше кода, а также поддерживает NSDictionary , NSCoding , Printable , Hashable и Equatable

Пример:

  class User: EVObject { # extend EVObject method for the class var id: Int = 0 var name: String = "" var friends: [User]? = [] } # use like below let json:String = "{\"id\": 24, \"name\": \"Bob Jefferson\", \"friends\": [{\"id\": 29, \"name\": \"Jen Jackson\"}]}" let user = User(json: json) 

ObjectMapper :

  • Другой способ – использовать ObjectMapper. Это дает больше контроля, но также требует гораздо больше кода.

Пример:

  class User: Mappable { # extend Mappable method for the class var id: Int? var name: String? required init?(_ map: Map) { } func mapping(map: Map) { # write mapping code name <- map["name"] id <- map["id"] } } # use like below let json:String = "{\"id\": 24, \"name\": \"Bob Jefferson\", \"friends\": [{\"id\": 29, \"name\": \"Jen Jackson\"}]}" let user = Mapper().map(json) 

Примечание. Для поддержки современной библиотеки для JSON проверьте этот удивительный список Swift

Я немного поработал над меньшим решением, которое не требует наследования. Но он не был проверен много. Это довольно уродливый атм.

https://github.com/peheje/JsonSerializerSwift

Вы можете передать его на площадку для тестирования. Например, следующую структуру classов:

 //Test nonsense data class Nutrient { var name = "VitaminD" var amountUg = 4.2 var intArray = [1, 5, 9] var stringArray = ["nutrients", "are", "important"] } class Fruit { var name: String = "Apple" var color: String? = nil var weight: Double = 2.1 var diameter: Float = 4.3 var radius: Double? = nil var isDelicious: Bool = true var isRound: Bool? = nil var nullString: String? = nil var date = NSDate() var optionalIntArray: Array = [1, 5, 3, 4, nil, 6] var doubleArray: Array = [nil, 2.2, 3.3, 4.4] var stringArray: Array = ["one", "two", "three", "four"] var optionalArray: Array = [2, 4, 1] var nutrient = Nutrient() } var fruit = Fruit() var json = JSONSerializer.toJson(fruit) print(json) 

печать

 {"name": "Apple", "color": null, "weight": 2.1, "diameter": 4.3, "radius": null, "isDelicious": true, "isRound": null, "nullString": null, "date": "2015-06-19 22:39:20 +0000", "optionalIntArray": [1, 5, 3, 4, null, 6], "doubleArray": [null, 2.2, 3.3, 4.4], "stringArray": ["one", "two", "three", "four"], "optionalArray": [2, 4, 1], "nutrient": {"name": "VitaminD", "amountUg": 4.2, "intArray": [1, 5, 9], "stringArray": ["nutrients", "are", "important"]}} 

Наряду с Swift 4 (Foundation) теперь он поддерживается в обоих направлениях, строка JSON для объекта – объект для строки JSON. См. Документацию Apple здесь JSONDecoder (), и здесь JSONEncoder ()

Строка JSON для объекта

 let jsonData = jsonString.data(using: .utf8)! let decoder = JSONDecoder() let myStruct = try! decoder.decode(myStruct.self, from: jsonData) 

Объект Swift для JSONString

 let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted let data = try! encoder.encode(myStruct) print(String(data: data, encoding: .utf8)!) 

Вы можете найти все подробности и примеры здесь. Ultimate Guide to JSON Parsing With Swift 4

Это не идеальное / автоматическое решение, но я считаю, что это идиоматический и родной способ сделать это. Таким образом, вам не нужны никакие библиотеки или такие.

Создайте протокол, например:

 /// A generic protocol for creating objects which can be converted to JSON protocol JSONSerializable { private var dict: [String: Any] { get } } extension JSONSerializable { /// Converts a JSONSerializable conforming class to a JSON object. func json() rethrows -> Data { try JSONSerialization.data(withJSONObject: self.dict, options: nil) } } 

Затем выполните его в своем classе, например:

 class User: JSONSerializable { var id: Int var name: String var dict { return ["id": self.id, "name": self.name] } } 

Теперь:

 let user = User(...) let json = user.json() 

Примечание: если вы хотите, чтобы json был строкой, очень просто преобразовать в строку: String(data: json, encoding .utf8)

Не уверен, существует ли lib / framework, но если вы хотите сделать это автоматически, и вы бы хотели избежать ручного труда 🙂 придерживаться MirrorType

 class U { var id: Int var name: String init(id: Int, name: String) { self.id = id self.name = name } } extension U { func JSONDictionary() -> Dictionary { var dict = Dictionary() let mirror = reflect(self) var i: Int for i = 0 ; i < mirror.count ; i++ { let (childName, childMirror) = mirror[i] // Just an example how to check type if childMirror.valueType is String.Type { dict[childName] = childMirror.value } else if childMirror.valueType is Int.Type { // Convert to NSNumber for example dict[childName] = childMirror.value } } return dict } } 

Возьмем это как примерный пример, не хватает надлежащей поддержки конвертации, не хватает рекурсии, ... Это просто демонстрация MirrorType ...

PS Здесь это делается в U , но вы собираетесь улучшить NSManagedObject а затем сможете конвертировать все подclassы NSManagedObject . Не нужно реализовывать это во всех подclassах / управляемых объектах.

Это пример кода в utf8.

 struct Person: Codable { var name: String var id: Int } // Encode let p = Person(name: "test", id: 1) let jsonEncoder = JSONEncoder() do { let jsonData = try jsonEncoder.encode(p) let jsonString = String(data: jsonData, encoding: .utf8) print("JSON String : " + jsonString!) } catch { print("error") } // Decode let jsonDecoder = JSONDecoder() let person = try jsonDecoder.decode(Person.self, from: jsonString) 
  • Как получить доступ к глубоко вложенным словарям в Swift
  • Общий форум
  • Swift Playground - Файлы недоступны для чтения
  • Как представить модальный поверх текущего вида в Swift
  • Как декодировать свойство с типом словаря JSON в Swift 4 decodable protocol
  • Абстрактные classы в языке Swift
  • Создание NSData из NSString в Swift
  • Доступ к базе данных SQLite в Swift
  • Как сделать случайное число между диапазоном для arc4random_uniform ()?
  • От String до NSDate в Swift
  • Получение «файла не обнаружено» в заголовке Bridging при импорте инфраструктур Objective-C в проект Swift
  • Interesting Posts

    Ошибка Webkit с `: hover` и несколькими соседними селекторами

    Почему я могу использовать auto в закрытом типе?

    Есть ли способ вычислить ширину целочисленного типа во время компиляции?

    Пользовательский агент Android HTTP

    Как отклонить AlertDialog в android

    Почему имена таблиц / столбцов / индексов Oracle ограничены 30 символами?

    Блокировка PSU при выключении

    Изменить идентификатор / идентификатор поставщика USB-устройства

    Каково значение знака вопроса в MySQL в столбце WHERE =??

    Sublime Text 2 – вставляет перерывы в соответствии с текущей упаковкой?

    Почему в Windows 7 по умолчанию не поддерживается Telnet?

    Почему я не должен использовать символы Unicode для имитации типографских стилей (например, небольших кепок или скриптов)?

    Список стилей Gmail

    Существует ли регулярное выражение для определения правильного регулярного выражения?

    как добавить день к дате с помощью jquery datepicker

    Давайте будем гением компьютера.