Kódovatelné vs ObjectMapper

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

Nedávno jsem experimentoval s novým protokolem Swift Codable jako způsobem, jak namapovat JSON přenesený ze vzdálené služby na objekt modelu Swift.

Pro trochu pozadí byl kódovatelný přidán do Swift 4 jako způsob, jak čistě umožnit objektům převést se do a z vnější reprezentace. Samotný kódovatelný je jen typealias dekódovatelného a kódovatelného.

U tohoto příspěvku se zaměřím na část Dekódovatelná, protože mě zajímá převedení ze vzdálené reprezentace JSON.

Srovnání

V minulosti jsem ObjectMapper hojně používal, ale protože Codable je nyní zabudován do Swift, chtěl jsem provést srovnání obou. Funkce, které chci porovnat, jsou:

  • Ověření ️
  • Vlastní transformace (mapování na vlastní typy, např. Mapování řetězce JSON do regexu)
  • Chyba při manipulaci

Data, která budu analyzovat, jsou skutečná konfigurace, kterou načteme vzdáleně pro aplikaci BBC Sport

Je to docela jednoduchá struktura JSON, ale má několik regulárních výrazů v tom, že bych chtěl být mapován na NSRegularExpression, nikoli na String

ObjectMapper

Struktury potřebné pro mapování tohoto modelu JSON pomocí ObjectMapper jsou následující.

Všechny produkty odpovídají protokolu ImmutableMappable, což znamená, že potřebují konstruktor, který vezme objekt Map a v případě selhání mapování vyvolá chybu.

Validace

Chcete-li provést ověření, můžete použít volitelné doplňky. V tomto příkladu jsme se rozhodli, že aplikace bude fungovat bez těchto e-mailových adres, takže e-maily jsou volitelné. map.values ​​(„e-maily“) vyvolá chybu, pokud klíč není k dispozici nebo jej nelze převést na správný typ. Využíváme vyzkoušet? zachytit tuto chybu a jednoduše ji změnit na nulovou hodnotu, pokud dojde k chybě.

Pokud se rozhodneme, že je požadována určitá vlastnost, nezaškrtneme ji jako volitelnou a povolíme šíření chyby.

Celkově je validace pomocí programu ImmitableMappable velmi přímá

Možná jste si všimli, že do této mapy volání je předán další argument.value („regex“, using: RegexTransformer ()) To je pro vlastní transformaci, aby se řetězec proměnil v NSRegularExpression, což mé pěkně vede k mému dalšímu bodu!

Vlastní transformace

ObjectMapper podporuje vlastní transformace po vybalení z krabice a je velmi přímý.

Právě implementujeme protokol TransformType a související metodu transformFromJSON. Převezme to typ, který vrhneme na String a poté bezpečně vyzkoušíme? převést řetězec na NSRegularExpression.

Tento transformátor je pak k dispozici pro opětovné použití kdekoli

Vypořádání se s chybou

K otestování zpracování chyb budu používat soubor JSON s chybějícím výstupním klíčem.

Při spuštění pomocí ObjectMapper dostaneme pěknou užitečnou chybovou zprávu.

Při mapování došlo k chybě.
- důvod: Nelze obsadit do řetězce „String“
- umístění: Config.init (mapa :): 30
- key: output
- currentValue: nil

Říká nám vše, co potřebujeme, abychom rychle našli, kde je problém. Při použití integrace AlamofireObjectMapper jsem zjistil, že chyby jsou potlačeny, což je méně než ideální.

Kódovatelný

Po vybalení je ekvivalentní implementace kódovatelná následovně

Je velmi podobný ObjectMapper, i když klíče jsou definovány jako výčty pomocí protokolu CodingKey.

Existuje opravdu pěkná funkce používající Codable v tom, že inicializátor může být vygenerován pro vás, pokud jsou výčtové případy stejné jako vlastnost, a typ, který mapujeme, je sám Dekódovatelný Příklad toho je CodableConfig výše. Protože všechny jeho vlastnosti jsou samy o sobě dekódovatelné, nemusíme psát inicializátor!

Validace

Funguje to úplně stejně jako ObjectMapper

Inicializátor vyvolá chybu, pokud došlo k mapování chyb, které lze zpracovat v místě volání. Opět zde využijte doplňků k rozhodnutí, jak nejlépe řešit chyby.

Vlastní transformace

Ve výše uvedeném kódu si všimnete, že když se pokusíme mapovat na náš typ NSRegularExpression, bude to všechno méně jasné. Najednou musíme implementovat inicializační iniciátor (z dekodéru: Dekodér) a získat sami KeyedDecodingContainer z dekodéru

K tomu už existuje skvělý zápis, pokud byste chtěli více podrobností, které sem nechystám.

Tento kód se nyní stane velmi podrobným, a nyní opakujeme transformační kód. V tomto případě je to jen další řádek, ale často se vyskytnou situace, kdy chci psát složitější transformace, které bych chtěl izolovat, jako bych mohl pomocí ObjectMapper

Takže jsem vytvořil malou knihovnu, abych přidal podporu pro vlastní transformace - je k dispozici přes CocoaPods, nebo byste mohli jen zkopírovat zdroj, protože je to jen pár souborů.

Můžete uvažovat o přidání rozšíření k typu, který nevlastníte, ale existuje dobré vysvětlení, proč to u Swift Evolution není možné.

Pomocí knihovny CodableExtensions můžeme nyní zjednodušit náš kód tak, aby vypadal velmi podobně jako ObjectMapper

A RegexCodableTransformer je také velmi podobný tomu, co jsme dříve měli s ObjectMapper

Knihovna také zjednodušuje rozhraní na container.decode (), takže typ již nemusí být předáván, jak je odvozeno.

Vypořádání se s chybou

Používám stejný soubor JSON k porovnání chybového zpracování jako předtím. Chyba vypadá

keyNotFound (config_spike.CodableRewriter. (CodingKeys v _4D474241C6D85B5C48988D77CA644850) .output, Swift.DecodingErrorConfig. ").", ZákladníVymazat: nula))

Tato chyba není tak docela vypadající , ale je tu vše, co problém vyladit.

Závěr

Existuje mnohem více podobností než rozdílů mezi těmito dvěma přístupy. Pokud jsou transformace důležité, ObjectMapper funguje mimo krabici. Jeden z hlavních motivátorů přechodu se však pohybuje na úroveň, kterou Apple vytvořil, aniž by musel přinést další knihovnu.

Pokud jsou transformace důležité, přidáním několika protokolů můžete dosáhnout stejného chování s kódovatelným

Rozhodli jsme se přejít na Codable nyní pro všechny naše nové funkce jdou vpřed. Určitě existují funkce, které jsem z tohoto seznamu vynechal, ale vybral jsem pro nás ty nejdůležitější.