Codable es una de las grandes novedades de iOS 11 en la Fundación de Swift. Un protocolo que, conformado con una clase o struct, permite que esta pueda generar instancias a partir de datos en un archivo JSON. Básicamente, el clásico concepto de la serialización de instancias, llevado a los nuevos tipos de Swift y sacando todo el partido al unirlo al formato estándar JSON.
La gran ventaja es que Codable
es un protocolo que incorpora dos implementaciones a través de extensiones de protocolos, que permite cargar de un JSON a instancias y de instancias hacia JSON con sus datos. Como vimos en esta guía ya publicada para Swift 3 (pulsando aquí), en vez de cargar un JSON en un diccionario con JSONSerialization
o un array de diccionarios y tener que acceder a las claves por cadenas y controlar opcionales, lo que tenemos es que **de un JSON podemos tener creadas todas las instancias necesarias y acceder a las propiedades como tales en una estructura de tipo de dato reconocible por todo el sistema.
Ejemplo
Vamos a suponer que tenemos un fichero MOCK_DATA que tiene la siguiente estructura:
[{"id":1,"first_name":"Linda","last_name":"Smith","email":"lsmith0@mtv.com","id_image":"https://robohash.org/eiuspraesentiumaut.png","username":"lsmith0","company":"Kimia"},
{"id":2,"first_name":"Sara","last_name":"Thompson","email":"sthompson1@statcounter.com","id_image":"https://robohash.org/quiavoluptaslaborum.png","username":"sthompson1","company":"Twimm"},
{"id":3,"first_name":"Martin","last_name":"Ferguson","email":"mferguson2@naver.com","id_image":"https://robohash.org/distinctioautperspiciatis.png","username":"mferguson2","company":"Mymm"}]
Esa estructura es un array de diccionarios, pero en nuestro caso podemos crear la estructura directamente en un struct y crear todas las instancias del tipo directamente. Para ello creamos el struct
:
struct Mock: Codable { var id:Int var first_name:String var last_name:String var email:String var id_image:String var username:String var company:String }
Es un struct
convencional con una diferencia clave: está conformado a Codable
. Un protocolo cuya obligatoriedad son dos funciones decode
y encode
que a través de extensiones de protocolos dan una implementación por defecto. Y si nos fijamos, el struct
tiene los mismos nombres de campos que tenemos en el JSON. Ahora hacemos la carga.
var datos:[Mock] = [] if let json = Bundle.main.path(forResource: "MOCK_DATA", ofType: "json"), let data = FileManager.default.contents(atPath: json) { let decoder = JSONDecoder() do { datos = try decoder.decode([Mock].self, from: data) } catch { print("Error: \(error.localizedDescription)") } }
Ya está. Cargamos en formato Data
el contenido del fichero MOCK_DATA
que tenemos en el Bundle
(como se haría normalmente para pasarle este tipo a JSONSerialization
), pero en vez de eso creamos un JSONDecoder
e invocamos el método decode
diciéndole que queremos recuperar un array de tipos Mock
(usando el .self
para acceder a la definición del propio tipo).
Desde luego una implementación no solo sencilla, sino práctica y limpia, porque nos permite no trabajar con diccionarios sino directamente con un tipo de dato asociado. En otras pequeñas guías veremos cómo hacer la operación contraria y personalizar la carga o descarga.
Probadlo y ya nos comentaréis qué os ha parecido. Un saludo y Good Apple Coding.