Izuzmite polja iz serializacije u Gsonu

1. Pregled

U ovom kratkom uputstvu istražit ćemo dostupne mogućnosti za izuzeće jednog ili više polja Java klase i njezinih podrazreda iz Gson serializacije.

2. Početno postavljanje

Prvo definirajmo svoje satove:

@Data @AllArgsConstructor javna klasa MyClass {private long id; privatni naziv niza; private String drugo; privatni podrazred MySubClass; } @Data @AllArgsConstructor javna klasa MySubClass {private long id; opis privatnog niza; private String otherVerboseInfo; } 

Za praktičnost smo im dodali Lombok (sintaktički šećer za getere, postavljače, konstruktore ...).

Ajmo ih sada popuniti:

MySubClass podrazred = novi MySubClass (42L, "odgovor", "Opširno polje da se ne serializira") MyClass izvor = novi MyClass (1L, "foo", "bar", podrazred); 

Cilj nam je spriječiti MyClass.drugo i MySubClass.otherVerboseInfo polja od serializacije.

Rezultat koji očekujemo je:

{"id": 1, "name": "foo", "subclass": {"id": 42, "description": "the answer"}} 

Na Javi:

Niz očekujeResult = "{\" id \ ": 1, \" name \ ": \" foo \ ", \" podrazred \ ": {\" id \ ": 42, \" description \ ": \" odgovor \ "}}"; 

3. Privremeni modifikator

Polje možemo označiti znakom prolazan modifikator:

javna klasa MyClass {private long id; privatni naziv niza; privatni prijelazni niz drugo; privatni podrazred MySubClass; } javna klasa MySubClass {private long id; opis privatnog niza; privatni prijelazni niz otherVerboseInfo; } 

Gson serializer zanemarit će svako polje proglašeno privremenim:

Niz jsonString = novi Gson (). ToJson (izvor); assertEquals (očekivani rezultat, jsonString); 

Iako je ovo vrlo brzo, dolazi i s ozbiljnom nedostatkom: svaki alat za serializaciju uzet će u obzir privremene promjene, ne samo Gson.

Privremeni je Java način da se izuzme iz serializacije, a zatim će i naše polje filtrirati Serijalizirati'S serializacija, i svaki bibliotečki alat ili okvir koji upravlja našim objektima.

Uz to, prolazan ključna riječ uvijek radi i za serializaciju i za deserializaciju, što može biti ograničenje, ovisno o slučajevima korištenja.

4. @Izložiti Bilješka

Gson com.google.gson.annotations @Izložiti anotacija djeluje obrnuto.

Pomoću njega možemo deklarirati koja polja serializirati, a zanemariti ostala:

javna klasa MyClass {@Expose private long id; @Expose privatni naziv niza; private String drugo; @ Izloži privatnu podklasu MySubClass; } javna klasa MySubClass {@Expose private long id; @Expose opis privatnog niza; private String otherVerboseInfo; } 

Za to moramo instancirati Gson pomoću GsonBuilder:

Gson gson = novi GsonBuilder () .excludeFieldsWithoutExposeAnnotation () .create (); Niz jsonString = gson.toJson (izvor); assertEquals (očekivani rezultat, jsonString); 

Ovaj put na razini polja možemo kontrolirati hoće li se filtriranje dogoditi za serializaciju, deserializaciju ili oboje (zadano).

Pogledajmo kako spriječiti MyClass.drugo od serializacije, ali dopuštanja da bude popunjena tijekom deserializacije iz JSON-a:

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

Iako je ovo najlakši način koji pruža Gson i ne utječe na ostale knjižnice, to bi moglo značiti suvišnost u kodu. Ako imamo klasu sa stotinu polja, a želimo isključiti samo jedno polje, trebamo napisati devedeset i devet napomena, što je pretjerano.

5. IsključenjeStrategija

Izuzetno prilagodljivo rješenje je korištenje a com.google.gson.IsključenjeStrategija.

Omogućuje nam da definiramo (izvana ili s Anonimous Inner Class) strategiju koja će uputiti GsonBuilder da li treba serializirati polja (i / ili klase) s prilagođenim kriterijima.

Gson gson = novi GsonBuilder () .addSerializationExclusionStrategy (strategija) .create (); Niz jsonString = gson.toJson (izvor); assertEquals (očekivani rezultat, jsonString); 

Pogledajmo nekoliko primjera pametnih strategija za korištenje.

5.1. S imenima klasa i polja

Naravno, možemo i tvrdo kodirati jedno ili više imena polja / klasa:

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

Ovo je brzo i izravno, ali nije baš za ponovnu upotrebu i također je sklono pogreškama u slučaju da preimenujemo svoje atribute.

5.2. S poslovnim kriterijima

Budući da jednostavno moramo vratiti logičku vrijednost, unutar te metode možemo implementirati svaku poslovnu logiku koja nam se sviđa.

U sljedećem ćemo primjeru identificirati svako polje koje započinje s „ostalo“ kao polja koja ne bi trebala biti serializirana, bez obzira na klasu kojoj pripadaju:

Strategija ExclusionStrategy = nova ExclusionStrategy () {@Preuzmi javni boolean shouldSkipClass (klasa klasa) {return false; } @Override public boolean shouldSkipField (FieldAttributes field) {return field.getName (). StartWith ("other"); }}; 

5.3. Uz prilagođenu napomenu

Još jedan pametan pristup je stvaranje prilagođene bilješke:

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

Tada možemo eksploatirati IsključenjeStrategija kako bi funkcionirao točno kao i kod @Izložiti napomena, ali obrnuto:

javna klasa MyClass {private long id; privatni naziv niza; @Exclude private String drugo; privatni podrazred MySubClass; } javna klasa MySubClass {private long id; opis privatnog niza; @Exclude private String otherVerboseInfo; } 

I evo strategije:

Strategija ExclusionStrategy = nova ExclusionStrategy () {@Preuzmi javni boolean shouldSkipClass (klasa klasa) {return false; } @Override public boolean shouldSkipField (polje FieldAttributes) {return field.getAnnotation (Exclude.class)! = Null; }}; 

Ovaj odgovor na StackOverflow prvo je opisao ovu tehniku.

Omogućuje nam da jednom napišemo napomenu i strategiju te da dinamički bilježimo svoja polja bez daljnjih izmjena.

5.4. Proširiti strategiju isključenja na deserijalizaciju

Bez obzira koju ćemo strategiju koristiti, uvijek možemo kontrolirati gdje je treba primijeniti.

Samo tijekom serializacije:

Gson gson = novi GsonBuilder (). AddSerializationExclusionStrategy (strategija) 

Samo tijekom deserializacije:

Gson gson = novi GsonBuilder (). AddDeserializationExclusionStrategy (strategija) 

Stalno:

Gson gson = novi GsonBuilder (). SetExclusionStrategies (strategija); 

6. Zaključak

Vidjeli smo različite načine za izuzimanje polja iz klase i njezinih podrazreda tijekom Gson serializacije.

Također smo istražili glavne prednosti i zamke svakog rješenja.

Kao i uvijek, puni izvorni kod dostupan je na Githubu.


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