parse jsonserialization data array json serialization swift

jsonserialization - parse json swift 4



Serialización JSON automática y deserialización de objetos en Swift (7)

Como se indica en WWDC2017 @ 24:48 ( Swift 4 ), podremos usar el protocolo codificable. Ejemplo

public struct Person : Codable { public let firstName:String public let lastName:String public let location:Location }

Entonces

let payload: Data = try JSONEncoder().encode(person)

Deserializar

let anotherPerson = try JSONDecoder().decode(Person.self, from: payload)

Todas las propiedades deben cumplir con el protocolo codificable.

Una alternativa , también puede ser JSONCodable que es utilizada por el generador de códigos de Swagger .

Estoy buscando una forma de serializar y deserializar automáticamente instancias de clase en Swift. Supongamos que hemos definido la siguiente clase ...

class Person { let firstName: String let lastName: String init(firstName: String, lastName: String) { self.firstName = firstName self.lastName = lastName } }

... y instancia de Person :

let person = Person(firstName: "John", lastName: "Doe")

La representación JSON de la person sería la siguiente:

{ "firstName": "John", "lastName": "Doe" }

Ahora, aquí están mis preguntas:

  1. ¿Cómo puedo serializar la instancia de person y obtener el JSON anterior sin tener que agregar manualmente todas las propiedades de la clase a un diccionario que se convierte en JSON?
  2. ¿Cómo puedo deserializar el JSON anterior y recuperar un objeto instanciado que está tipado estáticamente para que sea del tipo Person ? De nuevo, no quiero mapear las propiedades de forma manual.

Así es como lo harías en C # usando Json.NET :

var person = new Person("John", "Doe"); string json = JsonConvert.SerializeObject(person); // {"firstName":"John","lastName":"Doe"} Person deserializedPerson = JsonConvert.DeserializeObject<Person>(json);


Con Swift 4, simplemente tiene que hacer que su clase se ajuste a los Codable ( Encodable y Encodable ) para poder realizar serialización y deserialización JSON.

import Foundation class Person: Codable { let firstName: String let lastName: String init(firstName: String, lastName: String) { self.firstName = firstName self.lastName = lastName } }

Uso n. ° 1 (codifica una instancia de Person en una cadena JSON):

let person = Person(firstName: "John", lastName: "Doe") let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted // if necessary let data = try! encoder.encode(person) let jsonString = String(data: data, encoding: .utf8)! print(jsonString) /* prints: { "firstName" : "John", "lastName" : "Doe" } */

Uso # 2 (decodifica una cadena JSON en una instancia de Person ):

let jsonString = """ { "firstName" : "John", "lastName" : "Doe" } """ let jsonData = jsonString.data(using: .utf8)! let decoder = JSONDecoder() let person = try! decoder.decode(Person.self, from: jsonData) dump(person) /* prints: ▿ __lldb_expr_609.Person #0 - firstName: "John" - lastName: "Doe" */


Eche un vistazo a NSKeyValueCoding.h, específicamente setValuesForKeysWithDictionary . Una vez que deserialice el json en un NSDictionary , puede crear e inicializar su objeto con esa instancia de diccionario, sin necesidad de establecer valores manualmente en el objeto. Esto le dará una idea de cómo la deserialización podría funcionar con json, pero pronto descubrirá que necesita más control sobre el proceso de deserialización. Esta es la razón por la cual implemento una categoría en NSObject que permite la inicialización de NSObject completamente controlada con un diccionario durante la deserialización json, básicamente enriquece el objeto incluso más de lo que setValuesForKeysWithDictionary puede hacer. También tengo un protocolo utilizado por el deserializador json, que permite deserializar el objeto para controlar ciertos aspectos, por ejemplo, si deserializa un NSArray de objetos, le preguntará a ese objeto cuál es el nombre de tipo de los objetos almacenados en el conjunto.


Hay una clase Foundation llamada NSJSONSerialization que puede realizar conversiones desde y hacia JSON .

El método para convertir de JSON a un objeto se ve así:

let jsonObject = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary

Tenga en cuenta que el primer argumento para este método es la información JSON , pero no como un objeto de cadena, sino como un objeto NSData (que es la forma en que muchas veces obtendrá datos JSON de todos modos).

Lo más probable es que desee un método de fábrica para su clase que tome datos JSON como argumento, haga uso de este método y devuelva un objeto de inicialización de su clase.

Para invertir este proceso y crear datos JSON a partir de un objeto, querrá hacer uso de dataWithJSONObject , en el que pasará un objeto que se puede convertir en JSON y tener un NSData? devuelto. De nuevo, es probable que desee crear un método auxiliar que no requiera argumentos como método de instancia de su clase.

Hasta donde yo sé, la forma más fácil de manejar esto es crear una forma de mapear las propiedades de sus objetos en un diccionario y pasar ese diccionario para convertir su objeto en datos JSON. Luego, al convertir sus datos JSON en el objeto, espere que se devuelva un diccionario e invierta el proceso de asignación. Sin embargo, puede haber una manera más fácil.


Podría usar EVReflection para eso. Puede usar código como:

var person:Person = Person(json:jsonString)

o

var jsonString:String = person.toJsonString()

Consulte la página de GitHub para obtener un código de muestra más detallado. Solo tiene que hacer de EVObject la clase base de sus objetos de datos. No se necesita mapeo (siempre que las claves json sean las mismas que los nombres de las propiedades)

Actualización: Swift 4 tiene soporte para Codable, lo que lo hace casi tan fácil como EVReflection pero con un mejor rendimiento. Si desea utilizar un contratista fácil como el anterior, puede usar esta extensión: Stuff/Codable


Primero, crea un objeto Swift como este

struct Person { var firstName: String?; var lastName: String?; init() { } }

Después de eso, serialice los datos JSON que ha obtenido, utilizando la NSJSONSerialization incorporada y analice los valores en el objeto Person .

var person = Person(); var error: NSError?; var response: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(), error: &error); if let personDictionary = response as? NSDictionary { person.firstName = personDictionary["firstName"] as? String; person.lastName = personDictionary["lastName"] as? String; }

ACTUALIZAR:

También por favor eche un vistazo a esas bibliotecas

Swift-JsonSerialiser

ROJSONParser


Puede lograr esto utilizando la biblioteca ObjectMapper . Te dará más control sobre nombres de variables y los valores y el JSON preparado. Después de agregar esta biblioteca, amplíe la clase Mappable y defina la función de mapping(map: Map) .

Por ejemplo

class User: Mappable { var id: Int? var name: String? required init?(_ map: Map) { } // Mapping code func mapping(map: Map) { name <- map["name"] id <- map["id"] } }

Úselo como abajo

let user = Mapper<User>().map(JSONString)