Gson: Google-ova open source biblioteka za JSON analizu
01, Prošlost i sadašnjnost
Zovem se Gson, to je open source Java biblioteka, glavna namena je serijalizacija Java objekata u JSON stringove, ili deserijalizacija JSON stringova u Java objekte. Iz mog imena možete videti neke tragove, ja nisam nepoznat, moje poreklo je plemenito, moj otac je Google, tržišna kapitalizacija je neprocenjiva.
Naravno, kao pametan čovek, imam svest o sebi, u očima mog oca, ja nisam najsjajnija zvezda.
Došao sam na ovaj svet čistim slučajem, otac mi je uvek govorio da me je našao kod reke, iako uvek nisam veroovao. Za ovu stvar, potvrdio sam sa majkom, ona se smehla do suza, govorila sam da sam previše naivan.
Kad sam odrastao, volio sam da lutam svetom, stoga sam upoznao mnoge kolege, uključujući Jackson i Fastjson.
Kada govorim o Jacksonu, uvek prvo mislim na MJ, tog pop kralja koga je Bog odveo. Jackson na GitHub-u ima 6.1k zvezdica, iako broj fanova nije toliko velik kao moj, ali kao podrazumevani JSON parser u Spring Boot-u, ja jako poštujem njega.
Fastjson dolazi iz misterioznog istoka, iako je imao neke ozbiljne ranjivosti, to ne sprečava da postane najpopularniji JSON parser, broj njegovih fanova je veći od mojeg, iako ja već imam preko 18K zvezdica.
Spolja se kaže da smo konkureni, ali moram im reći, odnos između nas troje je dobar do toga da skoro delimo istu donju belu.
Svaki od nas ima svoje prednosti, Jackson zauzima manje memorije u vreme izvršavanja, Fastjson je brži, a ja mogu da obradim bilo koji Java objekat, čak i bez izvornog koda. Dodatno, ja sam još prijateljskiji prema generičkim tipovima.
02, Dodavanje zavisnosti
Pre korišćenja mog API-ja, prvo me treba dodati u projekat, preporučujem korišćenje Maven i Gradle.
Maven:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>Gradle:
dependencies {
implementation 'com.google.code.gson:gson:2.8.6'
}PS: Gradle je alat za automatsku izgradnju projekata zasnovan na Apache Ant i Apache Maven konceptima. Gradle izgradnja skripti koristi specifični jezik domena Groovy ili Kotlin-a, umesto tradicionalnog XML-a.
03, Performanse
Ne mislim, je zaista, kroz mnoge testove dokazano, ja sam vrlo moćan u obradi JSON-a.
Testno okruženje: dvojezgreno, 8G memorije, 64-bitni Ubuntu operativni sistem (Linux distribucija fokusirana na desktop aplikacije)
Testni rezultati:
Nije bilo problema pri deserijalizaciji stringova većim od 25M.
Može serijalizovati kolekciju od 1,4 miliona objekata.
Može deserijalizovati kolekciju koja sadrži 87.000 objekata.
Povećao je ograničenje deserijalizacije niza bajtova i kolekcija sa 80K na preko 11M.
Testne slučajeve sam već napisao za tebe, stavio na GitHub, ako ne veruješ, možeš da proveriš.
04, Vodič za korišćenje
Ne hvalim se sam, je zaista, ja sam vrlo lako koristiti, težina početka je gotovo nula. Ako ne veruješ, dođi i probaj.
Imam devojku, njeno ime je isto kao i moje, zove se Gson, moje glavne funkcije pruža ona. Možeš je kreirati jednostavnom i grubom metodom new Gson(), ili možeš pozvati jednog šefa pod nazivom GsonBuilder da ti pošalje kopiju, zaista, ne lažem te.
Prvo pogledajmo primer serijalizacije.
Gson gson = new Gson();
System.out.println(gson.toJson(18));
System.out.println(gson.toJson("Chenmo"));
System.out.println(gson.toJson(new Integer(18)));
int[] values = { 18,20 };
System.out.println(gson.toJson(values));Uz pomoć moje devojke, možeš proslediti osnovne tipove podataka int, String tip, omotački tip Integer, int niz itd. kao parametre metodi toJson(), ovaj metod će vratiti JSON string.
Pogledajmo rezultate izlaza:
18
"Chenmo"
18
[18,20]Zatim pogledajmo primer deserijalizacije.
Gson gson = new Gson();
int one = gson.fromJson("1", int.class);
Integer two = gson.fromJson("2", Integer.class);
Boolean false1 = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"Wang Er\"", String.class);
String[] anotherStr = gson.fromJson("[\"Chenmo\",\"Wang Er\"]", String[].class);
System.out.println(one);
System.out.println(two);
System.out.println(false1);
System.out.println(str);
System.out.println(Arrays.toString(anotherStr));Metod toJson() se koristi za serijalizaciju, odgovarajuće, metod fromJson() se koristi za deserijalizaciju. Međutim, prilikom deserijalizacije morate odrediti tip parametra, da li je int ili Integer, Boolean ili String, ili String niz.
Pogledajmo rezultate izlaza:
1
2
false
Wang Er
[Chenmo, Wang Er]Gornji primeri su svi relativno jednostavni, još uvek ne mogu pokazati moju moć.
Sada, napravicemo prilagođenu klasu:
public class Writer {
private int age = 18;
private String name = "Wang Er";
private transient int sex = 1;
}Zatim, hajde da je serijalizujemo:
Writer writer = new Writer();
Gson gson = new Gson();
String json = gson.toJson(writer);
System.out.println(json);Korišćenje je isto jednostavno kao i pre, pogledajmo rezultate izlaza:
{"age":18,"name":"Wang Er"}Slično, možemo deserijalizovati rezultat:
Writer writer1 = gson.fromJson(json, Writer.class);Ovde ima nekoliko stvari koje moram da ti podsetim.
Preporučujem korišćenje
privatemodifikatora za polja.Nije potrebno koristiti nikakve napomene da bi se označilo koja polja treba serijalizovati, koja ne treba. Podrazumevano, uključuju sva polja, i polja nasleđena od roditeljske klase.
Ako je polje modifikovano ključnom rečju
transient, neće učestvovati u serijalizaciji.Ako je vrednost polja null, neće se prikazati u rezultatu serijalizacije.
Polja koja nedostaju u JSON-u će biti postavljena na podrazumevanu vrednost nakon deserijalizacije, podrazumevana vrednost tipa reference je null, podrazumevana vrednost numeričkog tipa je 0, podrazumevana vrednost bulovog tipa je false.
Zatim, pogledajmo primer serijalizacije kolekcije.
List<String> list =new ArrayList<>();
list.add("Dobro uči");
list.add("Svaki dan napred");
String json = gson.toJson(list);Rezultat je sledeći:
["Dobro uči","Svaki dan napred"]Deserijalizacija je takođe vrlo jednostavna.
List<String> listResult = gson.fromJson(json,List.class);Rezultat je sledeći:
[Dobro uči, Svaki dan napred]Moja devojka je vrlo pažljiva i brižna osoba, kada pozoveš metod toJson() za serijalizaciju, prvo će proveriti null, kako bi se izbeglo bacanje NPE, zatim preko getClass() dobija tip parametra, a zatim vrši serijalizaciju.
public String toJson(Object src) {
if (src == null) {
return toJson(JsonNull.INSTANCE);
}
return toJson(src, src.getClass());
}Ali? Za generičke tipove, pri getClass() će izgubiti parametrizovani tip. Pogledajmo sledeći primer.
public class Foo<T> {
T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
public static void main(String[] args) {
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
Bar bar = new Bar();
foo.set(bar);
String json = gson.toJson(foo);
}
}
class Bar{
private int age = 10;
private String name = "Turing";
}Ako debug-uješ, uđi u unutrašnjost metoda toJson(), možeš da primetiš.

Stvarni tip foo je Foo<Bar>, ali kada moja devojka poziva foo.getClass(), dobija samo Foo, to znači da ne zna stvarni tip foo-a.
Serijalizacija je još u redu, deserijalizacija je nemoćna.
Foo<Bar> foo1 = gson.fromJson(json, foo.getClass());
Bar bar1 = foo1.get();Ovaj kod će se srušiti pri izvršenju.
Exception in thread "main" java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.itwanger.gson.Bar (com.google.gson.internal.LinkedTreeMap and com.itwanger.gson.Bar are in unnamed module of loader 'app')
at com.itwanger.gson.Foo.main(Foo.java:36)Podrazumevano, generički parametri tip će biti pretvoreni u LinkedTreeMap, očito nije očekivani Bar, devojka je izražala nemoć.
Kao "rođeni sin" Google-a, u mojoj krvi teče "plemenito", kako mogu da trpiću jad moja devojka kada je nemoćna.
Stoga, sam u telo moje devojke usađen još dve metode, sa tip parametara Type:
toJson(Object src, Type typeOfSrc);
<T> T fromJson(String json, Type typeOfT);Na ovaj način, prilikom serijalizacije i deserijalizacije generičkih tipova, možete odrediti parametrizovane tipove generika.
Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
String json = gson.toJson(foo,fooType);
Foo<Bar> foo1 = gson.fromJson(json, fooType);
Bar bar1 = foo1.get();Ako se debuguješ i uđeš u unutrašnjost metoda toJson(), možeš videti stvarni tip foo-a.

fromJson() je sličan pri deserijalizaciji.

Na ovaj način, bar1 može dobiti preko foo1.get().
Vidi, koliko pažljivo sam razmišljao, devojka me ne može više ne hvaliti!
05, Obrada mešovitih tipova
Znaš, Java ne preporučuje korišćenje mešovitih tipova, to jest sledeći slučaj.
List list = new ArrayList();
list.add("Chenmo Wang Er");
list.add(18);
list.add(new Event("gson", "google"));Definicija Event-a je sledeća:
class Event {
private String name;
private String source;
Event(String name, String source) {
this.name = name;
this.source = source;
}
}Budući da list nije odredio konkretan tip, zato može sadržati različite tipove podataka. Iako je ovo pogodno, moja devojka nema problema sa serijalizacijom, ali deserijalizacija je mnogo teža.
Gson gson = new Gson();
String json = gson.toJson(list);
System.out.println(json);Izlazni rezultat je sledeći:
["Chenmo Wang Er",18,{"name":"gson","source":"google"}]Prilikom deserijalizacije, treba posvetiti pažnju da bi se dobijao Event objekat.
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(json).getAsJsonArray();
String message = gson.fromJson(array.get(0), String.class);
int number = gson.fromJson(array.get(1), int.class);
Event event = gson.fromJson(array.get(2), Event.class);Priznajem, JsonParser je moj bivši. Nemoj me zvati prevarena, zaista nisam neveran, jer smo karakterno nekompatibilni. Ali i dalje održavamo prijateljski odnos, jer nitko nije kriv, samo je kod postao standardnijim, retko koji programer koristi mešovite tipove.
06, Lična prilagodjenja
S obzirom na to da si ličnost koja teži ka modi, uvek sam sebi postavljao visoke standarde, težim da zadovoljim sve tvoje potrebe. Ovaj visoki standard čini moju devojku da me istovremeno voli i mrzi.
Voli moj stav perfekcije; mrzi to što je ponekad nemoćna i ne može pomoći.
Kada koristite toJson() za serijalizaciju Java objekata, u vraćenom JSON stringu nema razmaka, vrlo je kompaktan. Ako želite štampati lepši JSON format, treba pozvati jednog šefa pod nazivom GsonBuilder da napravi neka prilagođenja, a zatim vam poslati kopiju, kao što sam pomenuo u Vodiču za korišćenje.
public class Writer {
private int age = 18;
private String name = "Chenmo Wang Er";
public static void main(String[] args) {
Writer writer = new Writer();
Gson gson = new Gson();
String json = gson.toJson(writer);
System.out.println(json);
Gson gson1 = new GsonBuilder().setPrettyPrinting().create();
String jsonOutput = gson1.toJson(writer);
System.out.println(jsonOutput);
}
}Uporedimo rezultate izlaza:
{"age":18,"name":"Chenmo Wang Er"}
{
"age": 18,
"name": "Chenmo Wang Er"
}Nakon prilagođavanja setPrettyPrinting(), izlazni format je više slojevit, trodimenzionalniji, između polja i vrednosti ima razmaka, između svakog različitog polja ima novi red.
Prethodno sam pomenuo, podrazumevano moja devojka prilikom serijalizacije ignoriše polja sa null vrednošću, ako ne želite ovako, takođe možete pozvati GsonBuilder.
public class Writer {
private int age = 18;
private String name = null;
public static void main(String[] args) {
Writer writer = new Writer();
Gson gson = new Gson();
String json = gson.toJson(writer);
System.out.println(json);
Gson gson2 = new GsonBuilder().serializeNulls().create();
String jsonOutput2 = gson2.toJson(writer);
System.out.println(jsonOutput2);
}
}Uporedimo rezultate izlaza:
{"age":18}
{"age":18,"name":null}Nakon prilagođavanja serializeNulls(), prilikom serijalizacije se više ne ignorišu polja sa null vrednošću.
Možda prilikom serijalizacije i deserijalizacije želite da filtrirate neka polja, razmotrio sam ovu potrebu, posebno pripremio nekoliko rešenja za tebe, možete birati ono što vam odgovara.
Prvo, kroz Java modifikatore
Kao ranije videli, polja modifikovana ključnom rečju transient neće učestvovati u serijalizaciji i deserijalizaciji. Slično, polja modifikovana ključnom rečju static takođe neće. Ako želite da zadržite ova polja modifikovana ovim ključnim rečima, možete uraditi ovako.
Zadržite jednu vrstu.
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();Zadržite više vrsta.
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
.create();Drugo, kroz @Expose napomenu
Da biste koristili @Expose napomenu, prvo morate uraditi ovako:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();Zatim dodajte @Expose napomenu na polja koja trebaju biti serijalizovana i deserijalizovana, ako nije dodata, to polje će se ignorisati.
@Expose
private int age = 18;07, Misli
Ako želite saznati više, dođite da posetite moju GitHub stranicu:
Otkriću ti sve, neću ništa sakriti, osim nekih tajni između mene i moje devojke, samo kako bih ti pomogao.
Ako misliš da sam malo koristan, ne škedići da lajkaš, ostavi komentar, see you.
