Vylúčte polia zo serializácie v Gson

1. Prehľad

V tomto krátkom tutoriáli preskúmame dostupné možnosti vylúčenia jedného alebo viacerých polí triedy Java a jej podtried zo serializácie Gson.

2. Počiatočné nastavenie

Najprv si zadefinujme naše triedy:

@Data @AllArgsConstructor verejná trieda MyClass {súkromné ​​dlhé ID; súkromné ​​meno reťazca; súkromné ​​String iné; súkromná podtrieda MySubClass; } @Data @AllArgsConstructor verejná trieda MySubClass {súkromné ​​dlhé ID; popis súkromného reťazca; private String otherVerboseInfo; } 

Pre pohodlie sme ich anotovali pomocou Lomboku (syntaktický cukor pre getrov, setterov, konštruktérov ...).

Naplňme ich teraz:

MySubClass subclass = new MySubClass (42L, "the answer", "Verbose field not to serialize") MyClass source = new MyClass (1L, "foo", "bar", subclass); 

Naším cieľom je zabrániť MyClass.other a MySubClass.otherVerboseInfo polia sa nebudú serializovať.

Výsledok, ktorý očakávame, je:

{"id": 1, "name": "foo", "podtrieda": {"id": 42, "description": "odpoveď"}} 

V Jave:

Reťazec expectResult = "{\" id \ ": 1, \" name \ ": \" foo \ ", \" podtrieda \ ": {\" id \ ": 42, \" description \ ": \" odpoveď \ "}}"; 

3. Prechodný modifikátor

Pole môžeme označiť pomocou prechodný modifikátor:

public class MyClass {private long id; súkromné ​​meno reťazca; súkromný prechodný reťazec iné; súkromná podtrieda MySubClass; } verejná trieda MySubClass {súkromné ​​dlhé ID; popis súkromného reťazca; súkromný prechodný reťazec otherVerboseInfo; } 

Serializátor Gson bude ignorovať každé pole deklarované ako prechodné:

Reťazec jsonString = nový Gson (). ToJson (zdroj); assertEquals (expectResult, jsonString); 

Aj keď je to veľmi rýchle, prichádza to aj s ťažkou nevýhodou: každý nástroj na serializáciu bude prechodne brať do úvahy, nielen Gson.

Prechodný spôsob Java je možné vylúčiť zo serializácie, potom bude naše pole odfiltrované aj pomocou SerializovateľnéSerializáciu a každý knižničný nástroj alebo rámec spravujúci naše objekty.

Okrem toho prechodný kľúčové slovo vždy funguje pre serializáciu aj deserializáciu, čo môže byť obmedzujúce v závislosti od prípadov použitia.

4. @ Vystaviť Anotácia

Gson com.google.gson.annotations @ Vystaviť anotácia funguje naopak.

Môžeme ho použiť na vyhlásenie, ktoré polia sa majú serializovať, a ignorovať ostatné:

verejná trieda MyClass {@Expose private long id; @Vystavte súkromné ​​meno reťazca; súkromné ​​String iné; @Expose private MySubClass subclass; } verejná trieda MySubClass {@Expose private long id; @Expose private String description; private String otherVerboseInfo; } 

Z tohto dôvodu musíme vytvoriť inštanciu Gson pomocou nástroja GsonBuilder:

Gson gson = nový GsonBuilder () .excludeFieldsWithoutExposeAnnotation () .create (); Reťazec jsonString = gson.toJson (zdroj); assertEquals (expectResult, jsonString); 

Tentokrát môžeme na úrovni poľa ovládať, či by malo dôjsť k filtrovaniu pre serializáciu, deserializáciu alebo oboje (predvolené).

Pozrime sa, ako tomu zabrániť MyClass.other nebude serializovaný, ale umožní jeho vyplnenie počas deserializácie z JSON:

@Expose (serialize = false, deserialize = true) private String other; 

Aj keď je to najjednoduchší spôsob poskytovaný spoločnosťou Gson, nemá to vplyv na ostatné knižnice, mohlo by to znamenať nadbytočnosť kódu. Ak máme triedu so stovkou polí a chceme vylúčiť iba jedno pole, musíme napísať deväťdesiatdeväť anotácií, čo je prehnané.

5. Stratégia vylúčenia

Vysoko prispôsobiteľným riešením je použitie a com.google.gson.Stratégia vylúčenia.

Umožňuje nám to definovať (externe alebo s Anonimous Inner Class) stratégiu, ktorá dá pokyn GsonBuilder, či má serializovať polia (a / alebo triedy) podľa vlastných kritérií.

Gson gson = new GsonBuilder () .addSerializationExclusionStrategy (strategy) .create (); Reťazec jsonString = gson.toJson (zdroj); assertEquals (expectResult, jsonString); 

Pozrime sa na niekoľko príkladov inteligentných stratégií, ktoré treba použiť.

5.1. S názvami tried a polí

Samozrejme môžeme napevno napísať aj jeden alebo viac názvov polí / tried:

ExclusionStrategy strategy = new ExclusionStrategy () {@Override public boolean shouldSkipField (FieldAttributes field) {if (field.getDeclaringClass () == MyClass.class && field.getName (). Equals ("other")) {return true; } if (field.getDeclaringClass () == MySubClass.class && field.getName (). equals ("otherVerboseInfo")) {return true; } return false; } @Override public boolean shouldSkipClass (Class clazz) {return false; }}; 

Je to rýchle a priame, ale nie príliš opakovane použiteľné a tiež náchylné na chyby v prípade, že premenujeme svoje atribúty.

5.2. S obchodnými kritériami

Pretože musíme jednoducho vrátiť boolovskú hodnotu, môžeme do tejto metódy implementovať každú obchodnú logiku, ktorá sa nám páči.

V nasledujúcom príklade identifikujeme každé pole začínajúce sa na „other“ ako polia, ktoré by sa nemali serializovať, bez ohľadu na to, do akej triedy patria:

ExclusionStrategy strategy = new ExclusionStrategy () {@Override public boolean shouldSkipClass (Class clazz) {return false; } @Override public boolean shouldSkipField (FieldAttributes field) {return field.getName (). StartsWith ("other"); }}; 

5.3. S vlastnou anotáciou

Ďalším inteligentným prístupom je vytvorenie vlastnej anotácie:

@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.FIELD) public @interface Exclude {} 

Potom môžeme vykorisťovať Stratégia vylúčenia aby to fungovalo presne ako s @ Vystaviť anotácia, ale inverzne:

public class MyClass {private long id; súkromné ​​meno reťazca; @ Vylúčiť súkromný reťazec iné; súkromná podtrieda MySubClass; } verejná trieda MySubClass {súkromné ​​dlhé ID; popis súkromného reťazca; @ Vylúčiť súkromný reťazec otherVerboseInfo; } 

A tu je stratégia:

ExclusionStrategy strategy = new ExclusionStrategy () {@Override public boolean shouldSkipClass (Class clazz) {return false; } @Override public boolean shouldSkipField (FieldAttributes field) {return field.getAnnotation (Exclude.class)! = Null; }}; 

Táto odpoveď StackOverflow najskôr opísala túto techniku.

Umožňuje nám to jednorazovo napísať anotáciu a Stratégiu a bez ďalších úprav dynamicky anotovať naše polia.

5.4. Rozšíriť stratégiu vylúčenia na deserializáciu

Bez ohľadu na to, ktorú stratégiu použijeme, vždy môžeme určiť, kde sa má uplatniť.

Iba počas serializácie:

Gson gson = nový GsonBuilder (). AddSerializationExclusionStrategy (stratégia) 

Iba počas deserializácie:

Gson gson = nový GsonBuilder (). AddDeserializationExclusionStrategy (stratégia) 

Vždy:

Gson gson = nový GsonBuilder (). SetExclusionStrategies (stratégia); 

6. Záver

Videli sme rôzne spôsoby, ako vylúčiť polia z triedy a jej podtried počas serializácie Gson.

Preskúmali sme tiež hlavné výhody a úskalia každého riešenia.

Celý zdrojový kód je ako vždy k dispozícii na stránkach Github.


$config[zx-auto] not found$config[zx-overlay] not found