Mezők kizárása a Gson sorosításából

1. Áttekintés

Ebben a rövid bemutatóban megvizsgáljuk azokat a lehetőségeket, amelyekkel kizárhatjuk a Java osztály egy vagy több mezőjét és annak alosztályait a Gson sorosításból.

2. Kezdeti beállítás

Először határozzuk meg osztályainkat:

@Data @AllArgsConstructor nyilvános osztály MyClass {private long id; privát karakterlánc neve; privát Húr egyéb; privát MySubClass alosztály; } @Data @AllArgsConstructor nyilvános osztály MySubClass {private long id; privát karakterlánc leírása; privát String egyébVerboseInfo; } 

A kényelem kedvéért jegyzeteltük őket a Lombok-ra (szintaktikus cukor szerelőknek, betétkészítőknek, kivitelezőknek).

Töltsük be most őket:

MySubClass alosztály = new MySubClass (42L, "a válasz", "A belsõ mezõ nem sorosít") MyClass forrás = új MyClass (1L, "foo", "bar", alosztály); 

Célunk a Sajátosztály.más és MySubClass.otherVerboseInfo mezők sorosítása.

A kimenet, amelyet várhatóan kapunk:

{"id": 1, "name": "foo", "subclass": {"id": 42, "description": "a válasz"}} 

Java-ban:

String várhatóResult = "{\" id \ ": 1, \" name \ ": \" foo \ ", \" alosztály \ ": {\" id \ ": 42, \" description \ ": \" a válasz \ "}}"; 

3. Átmeneti módosító

Jelölhetünk egy mezőt a átmeneti módosító:

nyilvános osztály MyClass {private long id; privát karakterlánc neve; privát tranziens String egyéb; privát MySubClass alosztály; } public class MySubClass {private long id; privát karakterlánc leírása; privát tranziens String egyébVerboseInfo; } 

A Gson serializer figyelmen kívül hagy minden átmenetinek nyilvánított mezőt:

Karakterlánc jsonString = új Gson (). ToJson (forrás); assertEquals (várható eredmény, jsonString); 

Bár ez nagyon gyors, súlyos hátrányokkal is jár: minden szerializációs eszköz figyelembe veszi a tranzienseket, nemcsak Gson.

A Transient a Java módja annak, hogy kizárjuk a sorosítástól, akkor a mi mezőnket is kiszűrjük SorosíthatóSorosítása, valamint minden objektumunkat kezelő könyvtári eszköz vagy keretrendszer által.

Ezenkívül a átmeneti kulcsszó mindig működik mind a szerializáció, mind a deserializáció esetében, ami a felhasználási esettől függően korlátozó lehet.

4. @Expose Megjegyzés

Gson com.google.gson.annotations @Expose az annotáció fordítva működik.

Használhatjuk a sorosítandó mezők deklarálásához, és a többiek figyelmen kívül hagyásához:

nyilvános osztály MyClass {@Expose private long id; @Expose private String név; privát Húr egyéb; @Expose privát MySubClass alosztály; } nyilvános osztály MySubClass {@Expose private long id; @Expose private String leírás; privát String egyébVerboseInfo; } 

Ehhez be kell állítanunk a Gson-t egy GsonBuilder-be:

Gson gson = new GsonBuilder () .excludeFieldsWithoutExposeAnnotation () .create (); Karakterlánc jsonString = gson.toJson (forrás); assertEquals (várható eredmény, jsonString); 

Ezúttal terepi szinten ellenőrizhetjük, hogy a szűrés történjen-e sorosítás, deserializáció vagy mindkét esetben (alapértelmezett).

Nézzük meg, hogyan lehet megelőzni Sajátosztály.más nem sorosítják, de lehetővé teszik annak feltöltését a JSON deserializációja során:

@Expose (serialize = false, deserialize = true) private String egyéb; 

Bár ez a legegyszerűbb módja a Gson által biztosított, és nem érinti a többi könyvtárat, redundanciát jelenthet a kódban. Ha száz mezővel rendelkező osztályunk van, és csak egy mezőt akarunk kizárni, akkor kilencvenkilenc annotációt kell írnunk, ami túlteljes.

5. ExclusionStrategy

Nagyon testreszabható megoldás az a használata com.google.gson.ExclusionStrategy.

Ez lehetővé teszi számunkra, hogy meghatározzunk (külsőleg vagy Anonimous belső osztály segítségével) egy stratégiát, amellyel utasíthatjuk a GsonBuildert arra, hogy a mezőket (és / vagy osztályokat) egyedi feltételekkel sorosítsa-e.

Gson gson = new GsonBuilder () .addSerializationExclusionStrategy (stratégia) .create (); Karakterlánc jsonString = gson.toJson (forrás); assertEquals (várható eredmény, jsonString); 

Lássunk néhány példát az intelligens stratégiákra.

5.1. Osztályok és mezők nevével

Természetesen keményen kódolhatunk egy vagy több mező / osztály nevet is:

ExclusionStrategy stratégia = new ExclusionStrategy () {@Orride public boolean shouldSkipField (FieldAttributes field) {if (field.getDeclaringClass () == MyClass.class && field.getName (). Egyenlő ("egyéb")) {return true; } if (field.getDeclaringClass () == MySubClass.class && field.getName (). egyenlő ("otherVerboseInfo")) {return true; } return false; } @Orride public boolean shouldSkipClass (Class clazz) {return false; }}; 

Ez gyors és egyenesen lényeges, de nem túl újrafelhasználható, és hajlamos a hibákra is, ha átnevezzük az attribútumainkat.

5.2. Üzleti kritériumokkal

Mivel egyszerűen logikai értéket kell adnunk, ezért minden üzleti logikát megvalósíthatunk a módszeren belül.

A következő példában minden, az „egyéb” kezdetű mezőt azonosítunk olyan mezőként, amelyeket nem szabad sorosítani, függetlenül attól az osztálytól, amelyhez tartoznak:

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

5.3. Egyéni jelöléssel

Egy másik okos megközelítés egy egyedi kommentár létrehozása:

@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.FIELD) public @interface Kizárás {} 

Ezután kihasználhatjuk ExclusionStrategy annak érdekében, hogy pontosan úgy működjön, mint a @Expose kommentár, de fordítva:

nyilvános osztály MyClass {private long id; privát karakterlánc neve; @Kizárja a privát karakterláncot; privát MySubClass alosztály; } public class MySubClass {private long id; privát karakterlánc leírása; @Kizárja a privát karakterláncot egyébVerboseInfo; } 

És itt van a stratégia:

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

Ez a StackOverflow válasz először ezt a technikát írta le.

Ez lehetővé teszi számunkra, hogy egyszer megírjuk az annotációt és a Stratégiát, és további módosítások nélkül dinamikusan jegyezzük fel a mezőinket.

5.4. A kizárási stratégia kiterjesztése a deserializációra

Nem számít, melyik stratégiát fogjuk használni, mindig ellenőrizhetjük, hol kell alkalmazni.

Csak a sorozatosítás során:

Gson gson = new GsonBuilder (). AddSerializationExclusionStrategy (stratégia) 

Csak deserializáció során:

Gson gson = new GsonBuilder (). AddDeserializationExclusionStrategy (stratégia) 

Mindig:

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

6. Következtetés

Különböző módszereket láthattunk a mezők kizárására az osztályból és annak alosztályaiból a Gson sorosítása során.

Megvizsgáltuk minden megoldás fő előnyeit és buktatóit is.

Mint mindig, a teljes forráskód elérhető a Githubon.