Codable vs ObjectMapper

Foto de https://unsplash.com/photos/_rNVw54xZZg

Fa poc he estat experimentant amb el nou protocol codificable de Swift com una forma de fer un mapa JSON recollit des d'un servei remot en un objecte model Swift.

Per obtenir una mica de fons, es va afegir Codable a Swift 4 com una manera de permetre que els objectes es convertissin ells mateixos dins i fora d'una representació externa. El propi codificable és només un tipus de descodificable i codificable.

Per a aquesta publicació m'incidiré en la part descodificable, ja que és la conversió d'una representació JSON remota que m'interessa.

Comparació

He utilitzat ObjectMapper àmpliament en el passat, però com ara Codable es va integrar a Swift, volia fer una comparació dels dos. Les funcions que vull comparar són:

  • Validació ️
  • Transformació personalitzada (mapeig a tipus personalitzats, per exemple, mapar una cadena JSON en un regex)
  • S'ha produït un error al manejar

Les dades que analitzaré són reals configuracions que obtenim de forma remota per a l'aplicació BBC Sport

És una estructura JSON força simple, però té un parell d'expressions regulars perquè voldria ser mapejat a NSRegularExpression, no a una cadena

ObjectMapper

Les estructures necessàries per mapejar aquest model JSON amb ObjectMapper són les següents.

Tots els estutors s’ajusten al protocol ImmutableMappable, cosa que significa que necessiten un constructor que pren un objecte Map i que produeixi un error si el mapatge falla.

Validació

Per dur a terme la validació, podeu fer servir Opcionals. En aquest exemple, hem decidit que l'aplicació pot funcionar sense aquestes adreces de correu electrònic de manera que els correus electrònics són opcionals. map.values ​​("correus electrònics") llança un error si no hi són presents la clau o no es pot emetre al tipus correcte. Fem ús de try? per capturar aquest error i convertir-lo en un valor nul si hi ha un error.

Si decidim que es requereix una propietat determinada, no la marquem com a opcional i no permetem que es produeixi l’error.

En general, la validació és molt senzilla mitjançant ImmutableMappable

És possible que hagueu adonat que hi ha un argument addicional passat a aquesta trucada map.value ("regex", mitjançant: RegexTransformer ()) Això és la transformació personalitzada per convertir la cadena en NSRegularExpression, la qual cosa em porta bé al meu següent punt.

Transformació personalitzada

ObjectMapper és compatible amb les transformacions personalitzades i és molt senzill.

Aquí només implementem el protocol TransformType i el mètode transformFromJSON associat. Que cal tenir un tipus i que llencem a String i, seguidament, intentar-ho de manera segura? per convertir la cadena en una NSRegularExpression.

Aquest transformador ja està disponible per reutilitzar-lo a qualsevol lloc

Gestió d'errors

Per provar el maneig d’errors, utilitzaré un fitxer JSON amb la clau de sortida que falta.

Quan s'executa això mitjançant ObjectMapper, obtenim un bon missatge d'error útil.

S'ha produït un error al fer el mapa.
- motiu: No es pot enviar a "Cadena"
- ubicació: Config.init (mapa :): 30
- clau: sortida
- Valor actual: nul

Ens explica tot el que necessitem per trobar ràpidament on es troba el problema. He trobat quan utilitzeu la integració AlamofireObjectMapper que els errors se suprimeixen, que és menys que ideal.

Codificable

A fora de caixa, l'implementació Codable equivalent és la següent

És molt semblant a ObjectMapper tot i que les claus es defineixen com a enums mitjançant el protocol CodingKey.

Hi ha una característica molt bonica amb Codable, ja que es pot generar l’inicialitzador si es consideren casos iguals a la propietat, i el tipus al qual mapem és Decodable. Un exemple d’això és CodableConfig. Com que totes les seves propietats són elles mateixes Decodables, no necessitem escriure un inicialitzador.

Validació

Funciona exactament igual que ObjectMapper

L’inicialitzador emet un error si hi ha un mapatge d’errors que es pot gestionar al lloc de trucades. Un cop més, feu un bon ús d’Opcionals aquí per decidir de quina manera podeu gestionar els errors.

Transformació personalitzada

En el codi anterior, quedarà una mica menys clar quan estem tractant de mapar el nostre tipus de NSRegularExpression. De sobte hem d’implementar l’inicialitzador init (del decodificador: Decodificador) i obtenir-nos un KeyedDecodingContainer del Decoder

Ja hi ha una gran redacció sobre això si voleu més detalls, que no passaré aquí.

El codi es converteix en veritable per escriure ara, i repetim el codi de transformació. En aquest cas només és una línia addicional, però sovint hi ha vegades que vull escriure transformacions més complexes que voldria aïllar com ho puc fer amb ObjectMapper

Així, vaig crear una petita biblioteca per afegir suport per a les transformacions personalitzades, això està disponible a través de CocoaPods o bé només podríeu copiar l'origen ja que són només un parell de fitxers.

Podeu pensar a afegir una extensió al tipus que no sou, però hi ha una bona explicació de per què això no és possible a Swift Evolution.

Mitjançant la biblioteca CodableExtensions, ara podem simplificar el nostre codi per semblar molt similar a ObjectMapper

I el RegexCodableTransformer també és molt similar al que vam tenir anteriorment amb ObjectMapper

La biblioteca també simplifica la interfície a container.decode () per la qual cosa ja no cal passar el tipus segons es va inferir.

Gestió d'errors

Utilitzo el mateix fitxer JSON per comparar la distribució d’errors que fins ara. L’error sembla

keyNotFound (config_spike.CodableRewriter. (CodingKeys a _4D474241C6D85B5C48988D77CA644850) .output, Swift.DecodingError.Context (codingPath: [config_spike.CodableConfig. ").", underrorError: nil))

L’error no és tan maco, però té tot per depurar el problema.

Conclusió

Hi ha moltes més semblances que diferències entre els dos enfocaments. Si les transformacions són importants, ObjectMapper no funciona. Tot i això, un dels principals motivadors per canviar és passar a l'estàndard que Apple han creat sense haver de portar cap altra biblioteca.

Si les transformacions són importants, afegint un parell de protocols, podeu obtenir el mateix comportament amb Codable

Hem decidit passar ara a Codable per avançar totes les noves funcions. Estic segur que hi ha funcions que m’han perdut d’aquesta llista, però he escollit les més importants per a nosaltres.