Jackson vs Gson

1. Úvod

V tomto článku porovnáme rozhrania Gson a Jackson API na serializáciu a deserializáciu údajov JSON na objekty Java a naopak.

Gson a Jackson sú kompletné knižnice ponúkajúce podporu viazania údajov JSON pre Javu. Každý z nich je aktívne vyvinutý open-source projekt, ktorý ponúka prácu so zložitými dátovými typmi a podporu pre Java Generics.

A vo väčšine prípadov môžu obe knižnice rekonštruovať entitu bez úpravy triedy entity, čo je dôležité v prípadoch, keď vývojár nemá prístup k zdrojovému kódu entity.

2. Závislosť Gson Maven

 com.google.code.gson gson $ {gson.version} 

Najnovšiu verziu aplikácie Gson nájdete tu.

3. Gson serializácia

Serializácia prevádza objekty Java na výstup JSON. Zvážte nasledujúce entity:

verejná trieda ActorGson {private String imdbId; súkromné ​​Dátum dateOfBirth; súkromná zoznamová filmografia; // getre a setre, predvolený konštruktor a konštruktor poľa sú vynechané} verejná trieda Movie {private String imdbId; súkromný riaditeľ reťazca; subjekty súkromného zoznamu; // getre a setre, predvolený konštruktor a konštruktor poľa sú vynechané}

3.1. Jednoduchá serializácia

Začnime príkladom serializácie Java na JSON:

SimpleDateFormat sdf = nový SimpleDateFormat ("dd-MM-rrrr"); ActorGson rudyYoungblood = nový ActorGson ("nm2199632", sdf.parse ("21-09-1982"), Arrays.asList ("Apocalypto", "Beatdown", "Wind Walkers")); Movie movie = new Movie ("tt0472043", "Mel Gibson", Arrays.asList (rudyYoungblood)); Reťazec serializedMovie = nový Gson (). ToJson (film);

Výsledkom bude:

{"imdbId": "tt0472043", "director": "Mel Gibson", "herci": [{"imdbId": "nm2199632", "dateOfBirth": "21. septembra 1982 0:00:00", " filmography ": [" Apocalypto "," Beatdown "," Wind Walkers "]}]}

Predvolene:

  • Všetky vlastnosti sú serializované, pretože nemajú č nulový hodnoty
  • dátum narodenia pole bolo preložené s predvoleným vzorom dátumu Gson
  • Výstup nie je naformátovaný a názvy vlastností JSON zodpovedajú entitám Java

3.2. Vlastná serializácia

Používanie vlastného serializátora nám umožňuje upraviť štandardné správanie. Môžeme predstaviť výstupný formátovač s HTML, handle nulový hodnoty, vylúčiť vlastnosti z výstupu alebo pridať nový výstup.

ActorGsonSerializer upravuje generovanie kódu JSON pre HerecGson element:

verejná trieda ActorGsonSerializer implementuje JsonSerializer {private SimpleDateFormat sdf = nový SimpleDateFormat ("dd-MM-rrrr"); @Override public JsonElement serialize (herec ActorGson, typ typu, JsonSerializationContext jsonSerializationContext) {JsonObject actorJsonObj = nový JsonObject (); herecJsonObj.addProperty ("Kód IMDB", herec.getImdbId ()); herecJsonObj.addProperty ("Dátum narodenia", herec.getDateOfBirth ()! = null? sdf.format (herec.getDateOfBirth ()): null); herecJsonObj.addProperty ("Č. Filmu: ", herec.getFilmography ()! = null? herec.getFilmography (). size (): null); herecJsonObj.addProperty (" filmography ", herec.getFilmography ()! = null? convertFilmography (actor.getFilmography ()): null); návratový herecJsonObj;} súkromný reťazec convertFilmography (zoznam filmografie) {návrat filmography.stream () .collect (Collectors.joining ("-"));}}

S cieľom vylúčiť riaditeľ majetok, @ Vystaviť anotácia sa používa pre vlastnosti, ktoré chceme zvážiť:

verejná trieda MovieWithNullValue {@Expose private String imdbId; súkromný riaditeľ reťazca; @ Vystavte súkromných aktérov Zoznamu; }

Teraz môžeme pokračovať v vytváraní objektov Gson pomocou GsonBuilder trieda:

Gson gson = new GsonBuilder () .setPrettyPrinting () .excludeFieldsWithoutExposeAnnotation () .serializeNulls () .disableHtmlEscaping () .registerTypeAdapter (ActorGson.class, new ActorGsonSerializer ()) .create ()) SimpleDateFormat sdf = nový SimpleDateFormat ("dd-MM-rrrr"); ActorGson rudyYoungblood = nový ActorGson ("nm2199632", sdf.parse ("21-09-1982"), Arrays.asList ("Apocalypto", "Beatdown", "Wind Walkers")); MovieWithNullValue movieWithNullValue = nový MovieWithNullValue (null, "Mel Gibson", Arrays.asList (rudyYoungblood)); Reťazec serializedMovie = gson.toJson (movieWithNullValue);

Výsledok je nasledovný:

{"imdbId": null, "herci": [{"Kód IMDB":" nm2199632 ","Dátum narodenia": "21-09-1982", "Č. Filmu: ": 3," filmography ":" Apocalypto-Beatdown-Wind Walkers "}]}

Všimni si:

  • výstup je naformátovaný
  • niektoré názvy vlastností sú zmenené a obsahujú HTML
  • nulový sú zahrnuté hodnoty a riaditeľ pole je vynechané
  • Dátum je teraz v dd-MM-rrrr formát
  • nová nehnuteľnosť je prítomná - N ° Film
  • filmography je formátovaná vlastnosť, nie predvolený zoznam JSON

4. Gson deserializácia

4.1. Jednoduchá deserializácia

Deserializácia prevádza vstup JSON na objekty Java. Na ilustráciu výstupu implementujeme natiahnuť() metóda v oboch triedach entít:

public class Movie {@Override public String toString () {return "Movie [imdbId =" + imdbId + ", director =" + director + ", actors =" + players + "]"; } ...} verejná trieda ActorGson {@Override public String toString () {return "ActorGson [imdbId =" + imdbId + ", dateOfBirth =" + dateOfBirth + ", filmografia =" + filmografia + "]"; } ...}

Potom použijeme serializovaný JSON a spustíme ho štandardnou Gsonovou deserializáciou:

Reťazec jsonInput = "{\" imdbId \ ": \" tt0472043 \ ", \" players \ ":" + "[{\" imdbId \ ": \" nm2199632 \ ", \" dateOfBirth \ ": \" 1982- 09-21T12: 00: 00 + 01: 00 \ "," + "\" filmografia \ ": [\" Apocalypto \ ", \" Beatdown \ ", \" Wind Walkers \ "]}]}" "; Movie outputMovie = new Gson (). FromJson (jsonInput, Movie.class); outputMovie.toString ();

Výstupom sme my, naše entity, vyplnené údajmi z nášho vstupu JSON:

Film [imdbId = tt0472043, režisér = null, herci = [ActorGson [imdbId = nm2199632, dateOfBirth = út 21. septembra 04:00:00 PDT 1982, filmografia = [Apocalypto, Beatdown, Wind Walkers]]]]]

Rovnako ako v prípade jednoduchého serializátora:

  • názvy vstupov JSON musia korešpondovať s názvami entít Java, alebo sú nastavené na hodnotu null.
  • dátum narodenia pole bolo preložené s predvoleným vzorom dátumu Gson, ignorujúce časové pásmo.

4.2. Vlastná deserializácia

Používanie vlastného deserializátora nám umožňuje upraviť štandardné správanie deserializátora. V takom prípade chceme, aby dátum odrážal správne časové pásmo pre dátum narodenia. Používame zvyk ActorGsonDeserializer na HerecGson subjekt na dosiahnutie tohto cieľa:

verejná trieda ActorGsonDeserializer implementuje JsonDeserializer {private SimpleDateFormat sdf = nový SimpleDateFormat ("rrrr-MM-dd'T'HH: mm: ss"); @Override public ActorGson deserialize (JsonElement json, typ typu, JsonDeserializationContext jsonDeserializationContext) hodí JsonParseException {JsonObject jsonObject = json.getAsJsonObject (); JsonElement jsonImdbId = jsonObject.get ("imdbId"); JsonElement jsonDateOfBirth = jsonObject.get ("dateOfBirth"); JsonArray jsonFilmography = jsonObject.getAsJsonArray ("filmografia"); ArrayList filmList = nový ArrayList (); if (jsonFilmography! = null) {for (int i = 0; i <jsonFilmography.size (); i ++) {filmList.add (jsonFilmography.get (i) .getAsString ()); }} ActorGson actorGson = nový ActorGson (jsonImdbId.getAsString (), sdf.parse (jsonDateOfBirth.getAsString ()), filmList); návratový herecGson; }}

Zamestnali sme a SimpleDateFormat syntaktický analyzátor na analýzu vstupného dátumu, ktorý zohľadňuje časové pásmo.

Všimnite si, že sme sa mohli rozhodnúť jednoducho napísať vlastný deserializátor iba pre dátum, ale ActorGsonDeserializer ponúka podrobnejší pohľad na proces deserializácie.

Upozorňujeme tiež, že Gsonov prístup nevyžaduje úpravu HerecGson entita, čo je ideálne, pretože nie vždy môžeme mať prístup k vstupnej entite. Tu používame vlastný deserializátor:

Reťazec jsonInput = "{\" imdbId \ ": \" tt0472043 \ ", \" players \ ":" + "[{\" imdbId \ ": \" nm2199632 \ ", \" dateOfBirth \ ": \" 1982- 09-21T12: 00: 00 + 01: 00 \ ", + \" filmografia \ ": [\" Apocalypto \ ", \" Beatdown \ ", \" Wind Walkers \ "]}]}" "; Gson gson = new GsonBuilder () .registerTypeAdapter (ActorGson.class, new ActorGsonDeserializer ()) .create (); Movie outputMovie = gson.fromJson (jsonInput, Movie.class); outputMovie.toString ();

Výstup je podobný výsledku jednoduchého deserializátora, ibaže dátum používa správne časové pásmo:

Film [imdbId = tt0472043, režisér = null, herci = [ActorGson [imdbId = nm2199632, dateOfBirth = út 21. septembra 12:00:00 PDT 1982, filmografia = [Apocalypto, Beatdown, Wind Walkers]]]]]

5. Závislosť Jacksona Mavena

 com.fasterxml.jackson.core jackson-databind $ {jackson.version} 

Najnovšiu verziu Jacksona nájdete tu.

6. Jacksonova serializácia

6.1. Jednoduchá serializácia

Tu použijeme Jackson na získanie rovnakého serializovaného obsahu, aký sme mali so spoločnosťou Gson, pomocou nasledujúcich entít. Upozorňujeme, že osoby prijímajúce / nastavujúce entity musia byť verejné:

verejná trieda ActorJackson {private String imdbId; súkromné ​​Dátum dateOfBirth; súkromná zoznamová filmografia; // povinní hľadači a nastavovatelia, predvolený konštruktor // a podrobnosti konštruktora poľa vynechané} verejná trieda Film {súkromný reťazec imdbId; súkromný riaditeľ reťazca; súkromní aktéri Zoznamu; // povinní hľadači a nastavovatelia, predvolený konštruktor // a podrobnosti konštruktora poľa vynechané} SimpleDateFormat sdf = nový SimpleDateFormat ("dd-MM-rrrr"); ActorJackson rudyYoungblood = nový ActorJackson ("nm2199632", sdf.parse ("21-09-1982"), Arrays.asList ("Apocalypto", "Beatdown", "Wind Walkers")); Movie movie = new Movie ("tt0472043", "Mel Gibson", Arrays.asList (rudyYoungblood)); ObjectMapper mapovač = nový ObjectMapper (); Reťazec jsonResult = mapper.writeValueAsString (film);

Výstup je nasledovný:

{"imdbId": "tt0472043", "director": "Mel Gibson", "herci": [{"imdbId": "nm2199632", "dateOfBirth": 401439600000, "filmography": ["Apocalypto", "Beatdown" , "Wind Walkers"]}]}

Niekoľko zaujímavostí:

  • ObjectMapper je náš serializátor / deserializátor Jackson
  • Výstupný formát JSON nie je naformátovaný
  • Predvolene je Java Date preložený do dlho hodnotu

6.2. Vlastná serializácia

Môžeme vytvoriť Jacksonov serializátor pre Herec Jackson generovanie prvkov rozšírením StdSerializer pre našu entitu. Znova upozorňujeme, že obstarávatelia / nastavovatelia entít musia byť verejní:

public class ActorJacksonSerializer rozširuje StdSerializer {private SimpleDateFormat sdf = nový SimpleDateFormat ("dd-MM-rrrr"); public ActorJacksonSerializer (trieda t) {super (t); } @Override public void serialize (herec ActorJackson, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) hodí IOException {jsonGenerator.writeStartObject (); jsonGenerator.writeStringField ("imdbId", herec.getImdbId ()); jsonGenerator.writeObjectField ("dateOfBirth", herec.getDateOfBirth ()! = null? sdf.format (herec.getDateOfBirth ()): null); jsonGenerator.writeNumberField ("N ° Film:", actor.getFilmography ()! = null? herec.getFilmography (). size (): null); jsonGenerator.writeStringField ("filmografia", herec.getFilmography () .stream (). collect (Collectors.joining ("-"))); jsonGenerator.writeEndObject (); }}

Vytvoríme entitu filmu, ktorá umožní ignorovanie súboru riaditeľ lúka:

verejná trieda MovieWithNullValue {private String imdbId; @JsonIgnore súkromný riaditeľ reťazca; subjekty súkromného zoznamu; // povinní getri a nastavovatelia, predvolený konštruktor // a podrobnosti o konštruktore poľa vynechané}

Teraz môžeme pokračovať vo zvyku ObjectMapper vytvorenie a nastavenie:

SimpleDateFormat sdf = nový SimpleDateFormat ("dd-MM-rrrr"); ActorJackson rudyYoungblood = nový ActorJackson ("nm2199632", sdf.parse ("21-09-1982"), Arrays.asList ("Apocalypto", "Beatdown", "Wind Walkers")); MovieWithNullValue movieWithNullValue = nový MovieWithNullValue (null, "Mel Gibson", Arrays.asList (rudyYoungblood)); Modul SimpleModule = nový SimpleModule (); module.addSerializer (nový ActorJacksonSerializer (ActorJackson.class)); ObjectMapper mapovač = nový ObjectMapper (); Reťazec jsonResult = mapper.registerModule (modul) .writer (nový DefaultPrettyPrinter ()) .writeValueAsString (movieWithNullValue);

Výstup je naformátovaný vo formáte JSON, ktorý spracováva nulový hodnoty, formátuje dátum, vylučuje riaditeľ pole a zobrazuje nový výstup súboru Č:

{"herci": [{"imdbId": "nm2199632", "dateOfBirth": "21-09-1982", "N ° Film:": 3, "filmography": "Apocalypto-Beatdown-Wind Walkers"}] , "imdbID": null}

7. Jacksonova deserializácia

7.1. Jednoduchá deserializácia

Na ilustráciu výstupu implementujeme natiahnuť() metóda v obidvoch triedach entít Jackson:

public class Movie {@Override public String toString () {return "Movie [imdbId =" + imdbId + ", director =" + director + ", actors =" + players + "]"; } ...} verejná trieda ActorJackson {@Override public String toString () {return "ActorJackson [imdbId =" + imdbId + ", dateOfBirth =" + dateOfBirth + ", filmografie =" + filmografia + "]"; } ...}

Potom použijeme serializovaný JSON a spustíme ho prostredníctvom Jacksonovej deserializácie:

Reťazec jsonInput = "{\" imdbId \ ": \" tt0472043 \ ", \" herci \ ": [{\" imdbId \ ": \" nm2199632 \ ", \" dateOfBirth \ ": \" 1982-09-21T12 : 00: 00 + 01: 00 \ ", \" filmografia \ ": [\" Apocalypto \ ", \" Beatdown \ ", \" Wind Walkers \ "]}]}}"; ObjectMapper mapovač = nový ObjectMapper (); Film film = mapper.readValue (jsonInput, Movie.class);

Výstupom sme my, naše entity, vyplnené údajmi z nášho vstupu JSON:

Film [imdbId = tt0472043, režisér = null, herci = [ActorJackson [imdbId = nm2199632, dateOfBirth = út 21. septembra 04:00:00 PDT 1982, filmografia = [Apocalypto, Beatdown, Wind Walkers]]]]]

Rovnako ako v prípade jednoduchého serializátora:

  • názvy vstupov JSON musia korešpondovať s názvami entít Java, alebo sú nastavené na nulový,
  • dátum narodenia pole bolo preložené s predvoleným Jacksonovým vzorom dátumu, časové pásmo bolo ignorované.

7.2. Vlastná deserializácia

Používanie vlastného deserializátora nám umožňuje upraviť štandardné správanie deserializátora.

V takom prípade chceme, aby dátum odrážal správne časové pásmo pre dátum narodenia, takže do nášho Jacksona pridáme DateFormatter ObjectMapper:

Reťazec jsonInput = "{\" imdbId \ ": \" tt0472043 \ ", \" director \ ": \" Mel Gibson \ ", \" actors \ ": [{\" imdbId \ ": \" nm2199632 \ ", \ "dateOfBirth \": \ "1982-09-21T12: 00: 00 + 01: 00 \", \ "filmografia \": [\ "Apocalypto \", \ "Beatdown \", \ "Wind Walkers \"] }]} "; ObjectMapper mapovač = nový ObjectMapper (); DateFormat df = nový SimpleDateFormat ("rrrr-MM-dd'T'HH: mm: ss"); mapper.setDateFormat (df); Film film = mapper.readValue (jsonInput, Movie.class); film.toString ();

Výstup odráža správne časové pásmo s dátumom:

Film [imdbId = tt0472043, režisér = Mel Gibson, herci = [ActorJackson [imdbId = nm2199632, dateOfBirth = út 21. septembra 12:00:00 PDT 1982, filmografia = [Apocalypto, Beatdown, Wind Walkers]]]]]

Toto riešenie je čisté a jednoduché.

Prípadne by sme mohli vytvoriť vlastný deserializátor pre Herec Jackson triedy, zaregistroval tento modul u nás ObjectMappera rekonštruovali dátum pomocou @JsonDeserialize anotácia k Herec Jackson subjekt.

Nevýhodou tohto prístupu je potreba úpravy entity, čo nemusí byť ideálne riešenie pre prípady, keď nemáme prístup k triedam vstupných entít.

8. Záver

Gson aj Jackson sú dobrou voľbou na serializáciu / deserializáciu údajov JSON, jednoduché na použitie a dobre zdokumentované.

Výhody spoločnosti Gson:

  • Jednoduchosť toJson/odJsona v jednoduchých prípadoch
  • Na deserializáciu nepotrebujete prístup k entitám Java

Výhody spoločnosti Jackson:

  • Zabudované do všetkých rámcov JAX-RS (Jersey, Apache CXF, RESTEasy, Restlet) a Spring
  • Rozsiahla podpora anotácií

Kód pre Gsona a Jacksona nájdete na GitHub.


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