Jackson vs Gson

1. Bemutatkozás

Ebben a cikkben összehasonlítjuk a GSON és a Jackson API-kat a JSON adatok sorosításához és deszerializálásához a Java objektumokhoz és fordítva.

A Gson és a Jackson teljes könyvtárak, amelyek JSON adatkötési támogatást kínálnak a Java számára. Mindegyik aktívan fejlesztett nyílt forráskódú projekt, amelyek komplex adattípusok kezelését és a Java Generics támogatását kínálják.

És a legtöbb esetben mindkét könyvtár deserializálódhat egy entitásba anélkül, hogy módosítaná az entitásosztályt, ami fontos azokban az esetekben, amikor a fejlesztőnek nincs hozzáférése az entitás forráskódjához.

2. Gson Maven-függőség

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

A Gson legújabb verzióját itt szerezheti be.

3. Gson szerializálás

A szerializálás a Java objektumokat JSON kimenetté alakítja. Vegye figyelembe a következő entitásokat:

nyilvános osztály ActorGson {private String imdbId; privát Dátum dateOfBirth; privát List filmográfia; // getterek és beállítók, alapértelmezett kivitelező és terepi kivitelező kihagyva} public class Movie {private String imdbId; privát vonósigazgató; privát lista szereplők; // getterek és beállítók, az alapértelmezett kivitelező és a terepi kivitelező kihagyva}

3.1. Egyszerű sorosítás

Kezdjük egy példával a Java - JSON sorozatszámra:

SimpleDateFormat sdf = új SimpleDateFormat ("éééé-hh-éééé"); ActorGson rudyYoungblood = új ActorGson ("nm2199632", sdf.parse ("1982-09-21"), Arrays.asList ("Apocalypto", "Beatdown", "Wind Walkers"); Filmfilm = új film ("tt0472043", "Mel Gibson", Arrays.asList (rudyYoungblood)); Karakterlánc serializedMovie = új Gson (). ToJson (film);

Ennek eredményeként:

{"imdbId": "tt0472043", "rendező": "Mel Gibson", "színészek": [{"imdbId": "nm2199632", "dateOfBirth": "1982. szeptember 21., 00:00:00", " filmográfia ": [" Apocalypto "," Beatdown "," Wind Walkers "]}]}

Alapértelmezés szerint:

  • Minden tulajdonság soros, mert nincs nulla értékek
  • születési dátum mezőt lefordították az alapértelmezett Gson dátummintával
  • A kimenet nincs formázva, és a JSON tulajdonságnevek megegyeznek a Java entitásokkal

3.2. Egyéni sorosítás

Egyéni sorosító használatával módosíthatjuk a szokásos viselkedést. Bevezethetünk egy HTML formátumú kimeneti formázót, kezelni nulla értékeket, kizárja a tulajdonságokat a kimenetből, vagy új kimenetet ad hozzá.

ActorGsonSerializer módosítja a JSON kód létrehozását a ActorGson elem:

public class ActorGsonSerializer megvalósítja a JsonSerializer {private SimpleDateFormat sdf = new SimpleDateFormat ("dd-MM-yyyy"); @Orride public JsonElement serialize (ActorGson színész, típus típus, JsonSerializationContext jsonSerializationContext) {JsonObject színészJsonObj = új JsonObject (); színészJsonObj.addProperty ("IMDB kód", színész.getImdbId ()); színészJsonObj.addProperty ("Születési dátum", színész.getDateOfBirth ()! = null? sdf.format (színész.getDateOfBirth ()): null); színészJsonObj.addProperty ("N ° Film: ", színész.getFilmography ()! = null? színész.getFilmography (). méret (): null); színészJsonObj.addProperty (" filmográfia ", színész.getFilmography ()! = null? convertFilmography (színész.getFilmography ()): null); return színészJsonObj;} private String convertFilmography (List filmography) {return filmography.stream () .collect (Collectors.joining ("-"));}}

A. Kizárása érdekében rendező ingatlan, az @Expose annotációt használunk azokra a tulajdonságokra, amelyeket figyelembe akarunk venni:

public class MovieWithNullValue {@Expose private String imdbId; privát vonósigazgató; @Kizárt privát lista szereplői; }

Most folytathatjuk a Gson objektum létrehozását a GsonBuilder osztály:

Gson gson = new GsonBuilder () .setPrettyPrinting () .excludeFieldsWithoutExposeAnnotation () .serializeNulls () .disableHtmlEscaping () .registerTypeAdapter (ActorGson.class, new ActorGsonSerializer ()); SimpleDateFormat sdf = új SimpleDateFormat ("éééé-hh-éééé"); ActorGson rudyYoungblood = új ActorGson ("nm2199632", sdf.parse ("1982-09-21"), Arrays.asList ("Apocalypto", "Beatdown", "Wind Walkers"); MovieWithNullValue movieWithNullValue = új MovieWithNullValue (null, "Mel Gibson", Arrays.asList (rudyYoungblood)); Karakterlánc serializedMovie = gson.toJson (movieWithNullValue);

Az eredmény a következő:

{"imdbId": null, "színészek": [{"IMDB kód":" nm2199632 ","Születési dátum": "21-09-1982", "N ° Film: ": 3," filmográfia ":" Apocalypto-Beatdown-Wind Walkers "}]}

Vegye figyelembe, hogy:

  • a kimenet formázva van
  • néhány tulajdonságnév megváltozott és HTML-t tartalmaz
  • nulla értékek szerepelnek, és a rendező mező elhagyva
  • Dátum most a éééé-hh-éé formátum
  • új ingatlan van jelen - N ° Film
  • a filmográfia formázott tulajdonság, nem az alapértelmezett JSON lista

4. Gson deserializáció

4.1. Egyszerű deserializáció

A deserializáció a JSON bemenetet Java objektumokká alakítja. A kimenet szemléltetésére a toString () módszer mindkét entitásosztályban:

public class Movie {@Orride public String toString () {return "Film [imdbId =" + imdbId + ", rendező =" + rendező + ", színészek =" + színészek + "]"; } ...} public class ActorGson {@Orride public String toString () {return "ActorGson [imdbId =" + imdbId + ", dateOfBirth =" + dateOfBirth + ", filmography =" + filmography + "]"; } ...}

Ezután felhasználjuk a sorosított JSON-t, és futtatjuk a szokásos Gson deserializáción keresztül:

Karakterlánc jsonInput = "{\" imdbId \ ": \" tt0472043 \ ", \" szereplői ":" + "[{\" imdbId \ ": \" nm2199632 \ ", \" dateOfBirth \ ": \" 1982- 09-21T12: 00: 00 + 01: 00 \ "," + "\" filmográfia ": [\" Apocalypto \ ", \" Beatdown \ ", \" Wind Walkers \ "]}]}" "; Film = új Gson (). Json-tól (jsonInput, Movie.class); outputMovie.toString ();

A kimenet mi vagyunk az entitásaink, a JSON bemenetünk adataival feltöltve:

Film [imdbId = tt0472043, rendező = null, színészek = [ActorGson [imdbId = nm2199632, dateOfBirth = kedd 21. kedd, 04:00:00 PDT, 1982, filmográfia = [Apocalypto, Beatdown, Wind Walkers]]]]

Ahogy az egyszerű sorosító esetében is történt:

  • a JSON bemeneti neveknek meg kell egyezniük a Java entitásnevekkel, vagy nullára vannak állítva.
  • születési dátum mezőt lefordították az alapértelmezett Gson dátummintával, figyelmen kívül hagyva az időzónát.

4.2. Egyéni deserializáció

Egyedi deserializer használatával módosíthatjuk a deserializer szokásos viselkedését. Ebben az esetben azt szeretnénk, ha a dátum a megfelelő időzónát tükrözné születési dátum. Egy szokást használunk ActorGsonDeserializer a ActorGson egység elérése érdekében:

public class ActorGsonDeserializer megvalósítja a JsonDeserializer {privát SimpleDateFormat sdf = új SimpleDateFormat ("éééé-hh-dd'T'HH: mm: ss"); @Orride public ActorGson deserialize (JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) dobja a JsonParseException {JsonObject jsonObject = json.getAsJsonObject (); JsonElement jsonImdbId = jsonObject.get ("imdbId"); JsonElement jsonDateOfBirth = jsonObject.get ("dateOfBirth"); JsonArray jsonFilmography = jsonObject.getAsJsonArray ("filmográfia"); ArrayList filmList = new ArrayList (); if (jsonFilmography! = null) {for (int i = 0; i <jsonFilmography.size (); i ++) {filmList.add (jsonFilmography.get (i) .getAsString ()); }} ActorGson actressGson = új ActorGson (jsonImdbId.getAsString (), sdf.parse (jsonDateOfBirth.getAsString ()), filmList); visszatérő színészGson; }}

Alkalmazottuk a SimpleDateFormat elemző a bemeneti dátum elemzéséhez, figyelembe véve az időzónát.

Vegye figyelembe, hogy úgy dönthettünk, hogy egyszerűen csak a Dátumra írunk egyedi deserializálót, de a ActorGsonDeserializer részletesebb képet nyújt a deserializációs folyamatról.

Vegye figyelembe azt is, hogy a Gson-megközelítés nem igényli a ActorGson entitás, ami ideális, mivel nem biztos, hogy mindig hozzáférünk a bemeneti entitáshoz. Itt használjuk az egyedi deserializátort:

Karakterlánc jsonInput = "{\" imdbId \ ": \" tt0472043 \ ", \" szereplői ":" + "[{\" imdbId \ ": \" nm2199632 \ ", \" dateOfBirth \ ": \" 1982- 09-21T12: 00: 00 + 01: 00 \ ", + \" filmográfia \ ": [\" Apocalypto \ ", \" Beatdown \ ", \" Wind Walkers \ "]}]}"; Gson gson = new GsonBuilder () .registerTypeAdapter (ActorGson.class, new ActorGsonDeserializer ()) .create (); Filmkimenet: Mozi = gson.jsonból (jsonInput, Film.osztály); outputMovie.toString ();

A kimenet hasonló az egyszerű deserializer eredményhez, kivéve, ha a dátum helyes időzónát használ:

Film [imdbId = tt0472043, rendező = null, színészek = [ActorGson [imdbId = nm2199632, dateOfBirth = kedd 21. kedd, 12:00:00 PDT, 1982, filmográfia = [Apocalypto, Beatdown, Wind Walkers]]]]

5. Jackson Maven-függőség

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

Jackson legújabb verzióját itt szerezheti be.

6. Jackson szerializáció

6.1. Egyszerű sorosítás

Itt Jackson segítségével fogjuk megszerezni ugyanazt a sorosított tartalmat, mint amilyen a Gsonnal volt, a következő entitások felhasználásával. Ne feledje, hogy az entitás beszerzőinek / beállítóinak nyilvánosaknak kell lenniük:

public class ActorJackson {private String imdbId; privát Dátum dateOfBirth; privát List filmográfia; // kötelező getterek és beállítók, alapértelmezett kivitelező // és a terepi kivitelező részletek kihagyva} public class Movie {private String imdbId; privát vonósigazgató; privát lista szereplői; // kötelező getterek és beállítók, alapértelmezett kivitelező // és a terepi kivitelező részletek el vannak hagyva} SimpleDateFormat sdf = new SimpleDateFormat ("dd-MM-yyyy"); ActorJackson rudyYoungblood = új ActorJackson ("nm2199632", sdf.parse ("1982-09-21"), Arrays.asList ("Apocalypto", "Beatdown", "Wind Walkers"); Filmfilm = új film ("tt0472043", "Mel Gibson", Arrays.asList (rudyYoungblood)); ObjectMapper mapper = új ObjectMapper (); Karakterlánc jsonResult = mapper.writeValueAsString (film);

A kimenet a következő:

{"imdbId": "tt0472043", "rendező": "Mel Gibson", "színészek": [{"imdbId": "nm2199632", "dateOfBirth": 401439600000, "filmográfia": ["Apocalypto", "Beatdown" , "Wind Walkers"]}]}

Néhány érdekes jegyzet:

  • ObjectMapper a Jackson szerializátorunk / deserializerünk
  • A kimeneti JSON nincs formázva
  • Alapértelmezés szerint a Java dátum lefordítva hosszú érték

6.2. Egyéni sorosítás

Készíthetünk egy Jackson sorosítót a SzínészJackson elemgenerálás az StdSerializer kiterjesztésével entitásunk számára. Ismét megjegyezzük, hogy az entitásszerzőknek / -beállítóknak nyilvánosaknak kell lenniük:

public class ActorJacksonSerializer kiterjeszti a StdSerializer {private SimpleDateFormat sdf = new SimpleDateFormat ("dd-MM-yyyy"); public ActorJacksonSerializer (t osztály) {super (t); } @Orride public void serialize (ActorJackson színész, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) dobja az IOException {jsonGenerator.writeStartObject (); jsonGenerator.writeStringField ("imdbId", színész.getImdbId ()); jsonGenerator.writeObjectField ("dateOfBirth", színész.getDateOfBirth ()! = null? sdf.format (színész.getDateOfBirth ()): null); jsonGenerator.writeNumberField ("N ° Film:", színész.getFilmography ()! = null? színész.getFilmography (). méret (): null); jsonGenerator.writeStringField ("filmográfia", színész.getFilmography () .stream (). gyűjt (Gyűjtők.csatlakozó ("-"))); jsonGenerator.writeEndObject (); }}

Létrehozunk egy Movie entitást, hogy lehetővé tegyük a rendező terület:

public class MovieWithNullValue {private String imdbId; @JsonIgnore privát húrigazgató; privát lista szereplői; // kötelező getterek és beállítók, az alapértelmezett konstruktor // és a terepi konstruktor részletei el vannak hagyva}

Most folytathatjuk a szokásokat ObjectMapper létrehozása és beállítása:

SimpleDateFormat sdf = új SimpleDateFormat ("éééé-hh-éééé"); ActorJackson rudyYoungblood = új ActorJackson ("nm2199632", sdf.parse ("1982-09-21"), Arrays.asList ("Apocalypto", "Beatdown", "Wind Walkers"); MovieWithNullValue movieWithNullValue = új MovieWithNullValue (null, "Mel Gibson", Arrays.asList (rudyYoungblood)); SimpleModule module = new SimpleModule (); module.addSerializer (új ActorJacksonSerializer (ActorJackson.class)); ObjectMapper mapper = új ObjectMapper (); Karakterlánc jsonResult = mapper.registerModule (modul) .writer (új DefaultPrettyPrinter ()) .writeValueAsString (movieWithNullValue);

A kimenetet JSON formázza, amely kezeli nulla értékek, formázza a dátumot, kizárja a rendező mezőben, és a N °:

{"színészek": [{"imdbId": "nm2199632", "dateOfBirth": "1982-09-21", "N ° Film:": 3, "filmográfia": "Apocalypto-Beatdown-Wind Walkers"}] , "imdbID": null}

7. Jackson deserializáció

7.1. Egyszerű deserializáció

A kimenet szemléltetésére a toString () módszer mindkét Jackson entitásosztályban:

public class Movie {@Orride public String toString () {return "Film [imdbId =" + imdbId + ", rendező =" + rendező + ", színészek =" + színészek + "]"; } ...} public class ActorJackson {@Orride public String toString () {return "ActorJackson [imdbId =" + imdbId + ", dateOfBirth =" + dateOfBirth + ", filmography =" + filmography + "]"; } ...}

Ezután felhasználjuk a sorosított JSON-ot és futtatjuk a Jackson deserializáción keresztül:

Karakterlánc jsonInput = "{\" imdbId \ ": \" tt0472043 \ ", \" szereplői ": [{\" imdbId \ ": \" nm2199632 \ ", \" dateOfBirth \ ": \" 1982-09-21T12 : 00: 00 + 01: 00 \ ", \" filmográfia ": [\" Apocalypto \ ", \" Beatdown \ ", \" Wind Walkers \ "]}]}}"; ObjectMapper mapper = új ObjectMapper (); Film film = mapper.readValue (jsonInput, Movie.class);

A kimenet mi vagyunk az entitásaink, a JSON bemenet adataival töltve fel:

Film [imdbId = tt0472043, rendező = null, színészek = [ActorJackson [imdbId = nm2199632, dateOfBirth = kedd 21. kedd, 04:00:00 PDT 1982, filmográfia = [Apocalypto, Beatdown, Wind Walkers]]]]

Ahogy az egyszerű sorosító esetében is történt:

  • a JSON bemeneti neveknek meg kell egyezniük a Java entitásnevekkel, vagy ezek értéke nulla,
  • születési dátum mezőt lefordították az alapértelmezett Jackson dátummintával, figyelmen kívül hagyva az időzónát.

7.2. Egyéni deserializáció

Egyedi deserializer használatával módosíthatjuk a deserializer szokásos viselkedését.

Ebben az esetben azt akarjuk, hogy a dátum tükrözze a megfelelő időzónát születési dátum, így hozzáadunk egy DateFormattert Jacksonunkhoz ObjectMapper:

Karakterlánc jsonInput = "{\" imdbId \ ": \" tt0472043 \ ", \" rendező \ ": \" Mel Gibson \ ", \" szereplők ": [{\" imdbId \ ": \" nm2199632 \ ", \ "dateOfBirth \": \ "1982-09-21T12: 00: 00 + 01: 00 \", \ "filmográfia \": [\ "Apocalypto \", \ "Beatdown \", \ "Wind Walkers \"] }]} "; ObjectMapper mapper = új ObjectMapper (); DateFormat df = new SimpleDateFormat ("éééé-HH-nn-T'HH: mm: ss"); mapper.setDateFormat (df); Filmfilm = mapper.readValue (jsonInput, Movie.class); film.toString ();

A kimenet a helyes időzónát tükrözi a dátummal:

Film [imdbId = tt0472043, rendező = Mel Gibson, színészek = [ActorJackson [imdbId = nm2199632, dateOfBirth = kedd 21. kedd, 12:00:00 PDT 1982, filmográfia = [Apocalypto, Beatdown, Wind Walkers]]]]

Ez a megoldás tiszta és egyszerű.

Alternatív megoldásként létrehozhattunk volna egy egyedi deserializátort a SzínészJackson osztály, regisztrálta ezt a modult a mi ObjectMapper, és deserializálta a dátumot a @JsonDeserialize kommentár a SzínészJackson entitás.

Ennek a megközelítésnek az a hátránya, hogy módosítani kell az entitást, ami nem biztos, hogy ideális azokban az esetekben, amikor nincs hozzáférésünk a bemeneti entitásosztályokhoz.

8. Következtetés

Gson és Jackson egyaránt jó lehetőségek a JSON-adatok sorosítására / deszerializálására, egyszerűen használhatóak és jól dokumentáltak.

A Gson előnyei:

  • Az egyszerűség Jsonnak/Json-tól az egyszerű esetekben
  • A deszerializáláshoz nincs szükség hozzáférésre a Java entitásokhoz

Jackson előnyei:

  • Beépítve az összes JAX-RS (Jersey, Apache CXF, RESTEasy, Restlet) és Spring keretbe
  • Kiterjedt annotációs támogatás

A GitHubon megtalálhatja Gson és Jackson kódját.