DECODABLE en Swift en Español
Decodable en Swift se usa para parsear el JSON recibido de backend a objetos de tu dominio. Al recibir una petición HTTP con URLSession normalmente usamos JSONDecoder para mapear esta información a una struct de nuestra app. Con Decodable podemos mapear Arrays, usar estrategías, etc
Tabla de contenido
La librería Standard de Swift define una forma standard para codificar y decodicar datos. Para adoptar esta implementación debemos conformar en nuestros tipos los protocolos Encodable o Decodable.
Al adoptar estos protocolos podemos implementar el codificador y decodificador para codificar o decodificar a JSON o a property list (el formato de los property list es como el info.plist de una app).
Podemos conformar los dos a la vez usando Codable.
Es realmente útil para mapear de JSON a modelos de nuestro domino, una práctica que es muy común en la mayoría de aplicaciones que hacen peticiones HTTP.
Codificar y decodificar automáticamente
La manera más simple de hacer un tipo codable es usar propiedades que ya estén conformando el protocolo codable. Ejemplos claros son: String, Int, Double, Date, Data y URL.
Un ejemplo seria:
Hemos creado una struct llamada User que conforma el protocolo Codable. Como tiene propiedades de tipo String y tipo Int, no tenemos que hacer nada (ya que las dos conforman Codable).
Hemos creado la variable data para simular que es el JSON que recibimos al hacer una petición HTTP a nuestro backend.
Luego creamos una instancia de nuestro JSONDecoder y le decimos que intente decodificar lo que hay dentro de la variable data con nuestra User struct. Como ves, tenemos un try? ya que este mapeo puede fallar.
El ejemplo que acabamos de ver es muy sencillo, vamos a ver uno con más campos:
Sin más, no hay ninguna complicación.
Coding Keys
Vamos a complicar aún más las cosas. La mayoría de veces cuando llamamos a un endpoint la key del JSON no coincide con el nombre de la propiedad de nuestro objeto de dominio. Fíjate que ahora la key donde viene el nombre del user es "name_of_user":
Al implementar CodingKeys hacemos ese mapeo del JSON al nombre de la propiedad. Y el resultado es exactamente como el ejemplo anterior. Omitimos crear el enum CodingKeys cuando las keys del JSON coinciden con los de nuestra struct.
Decoder
Vamos a ver lo que ocurre en el inicializador con Decoder. Hasta ahora no lo hemos puesto ya que no lo hemos necesitado. En los ejemplos anteriores, Swift la ha generado por nosotros (cuando son casos sencillos, la mayoría de veces serán procesos transparentes para nosotros). Vamos a ver otra vez como quedaría el primer ejemplo, pero esta vez con todo el código que genera Swift por nosotros:
Dentro del método init, le decimos al decodificador que tendremos un container con las CodingKeys que hemos especificado en el enum. Y luego, accedemos al container para sacar cada valor y asignarselo a la propiedades de nuestra instancia.
Decodificar un Array
Hasta ahora hemos visto un ejemplo sencillo de cómo mapear un una única instancia de nuestro modelo de dominio. Vamos a ver otro ejemplo para ver cómo mapeamos cuando recibimos un listado de usuarios.
Como ves, es muy similar hasta lo ya visto en este post. La clave de todo está en esta línea, donde especificamos que esperamos un array de Users:
let users = try JSONDecoder().decode([User].self, from: data)
Estrategias para Decodificar
En Swift 4.1 añadieron la propierdad keyDecodingStrategy como propiedad del JSONDecoder para poder usar distintas estrategias. Por ejemplo hay empresas/equipos que prefieren usar snake case "user_name".
Si tienes algún endpoint que devuelve la key con este formato "user_name", que sepas que puedes transformarlo fácilmente usando keyDecodingStrategy:
Hay más estrategías que puedes usar en tus decodificadores:
- dateDecodingStrategy
- dataDecodingStrategy
- nonConformingFloatDecodingStrategy
Hoy hemos visto una pincelada de lo que son los decodificadores y como los usamos para mapear de JSON a nuestros modelos de negocio. Pero hay mucho más que iremos viendo.
Como siempre puedes encontrar el código en Github
Hasta aquí el post de hoy, gracias por leernos! 🤓
Si tienes preguntas no dudes en contactar con nosotros a través de Twitter