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.