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.