Konverter JSON til et kort ved hjælp af Gson

1. Introduktion

I denne hurtige vejledning lærer vi, hvordan man konverterer en JSON-streng til en Kort ved brug af Gson fra Google.

Vi ser tre forskellige tilgange til at opnå det og diskutere deres fordele og ulemper - med nogle praktiske eksempler.

2. Aflevering Kort. Klasse

Generelt, Gson leverer følgende API i sin Gson klasse for at konvertere en JSON-streng til et objekt:

offentlig T fromJson (String json, Class classOfT) kaster JsonSyntaxException;

Fra signaturen er det meget klart, at den anden parameter er den klasse af objektet, som vi agter JSON at analysere i. I vores tilfælde burde det være det Kort. Klasse:

String jsonString = "{'medarbejder.navn': 'Bob', 'medarbejder.salar': 10000}"; Gson gson = ny Gson (); Kortkort = gson.fromJson (jsonString, Map.class); Assert.assertEquals (2, kort.størrelse ()); Assert.assertEquals (Double.class, map.get ("medarbejder.salar"). GetClass ());

Denne tilgang giver sit bedste gæt med hensyn til værditype for hver ejendom.

For eksempel tvinges tal ind i Dobbelts, rigtigt og falsk ind i Boolskog genstande ind i LinkedTreeMaps.

Hvis der er duplikatnøgler, mislykkes tvang imidlertid, og det vil kaste et JsonSyntaxException.

Og på grund af sletning af typen, vi vil heller ikke være i stand til at konfigurere denne tvangsadfærd. Så hvis vi har brug for at specificere nøgle- eller værdityperne, har vi brug for en anden tilgang.

3. Brug TypeToken

For at overvinde problemet med typesletning for de generiske typer, Gson har en overbelastet version af API'en:

offentlig T fromJson (String json, Type typeOfT) kaster JsonSyntaxException;

Vi kan konstruere en Kort med dens typeparametre ved hjælp af Gson's TypeToken. Det TypeToken klasse returnerer en forekomst af ParameterizedTypeImpl der bevarer typen af ​​nøgle og værdi, selv ved kørselstid:

String jsonString = "{'Bob': {'name': 'Bob Willis'}," + "'Jenny': {'name': 'Jenny McCarthy'}," + "'Steve': {'name': 'Steven Waugh'}} "; Gson gson = ny Gson (); Skriv empMapType = nyt TypeToken() {} .getType (); KortnavnEmployeeMap = gson.fromJson (jsonString, empMapType); Assert.assertEquals (3, nameEmployeeMap.size ()); Assert.assertEquals (Employee.class, nameEmployeeMap.get ("Bob"). GetClass ()); 

Nu, hvis vi konstruerer vores Kort skriv som Kort, så vil parseren stadig være standard som vi så i det foregående afsnit.

Selvfølgelig falder dette stadig tilbage til Gson for at tvinge primitive typer. Disse kan dog også tilpasses.

4. Brug af brugerdefineret JsonDeserializer

Når vi har brug for finkornet kontrol over opbygningen af ​​vores Kort objekt, kan vi implementere en brugerdefineret deserializer af typen JsonDeserializer.

For at se et eksempel, lad os antage, at vores JSON indeholder medarbejderens navn som nøgle og deres ansættelsesdato som værdi. Lad os antage, at datoens format er åååå / MM / dd, som ikke er et standardformat til Gson.

Vi kan konfigurere Gson til at analysere vores kort forskelligt ved derefter at implementere en JsonDeserializer:

offentlig klasse StringDateMapDeserializer implementerer JsonDeserializer {privat SimpleDateFormat-format = nyt SimpleDateFormat ("åååå / MM / dd"); @Override public Map deserialize (JsonElement elem, Type type, JsonDeserializationContext jsonDeserializationContext) {return elem.getAsJsonObject () .entrySet () .stream () .filter (e -> e.getValue (). IsJsonPrimitive ()) .filter. -> e.getValue (). getAsJsonPrimitive (). isString ()) .collect (Collectors.toMap (Map.Entry :: getKey, e -> formatDate (e.getValue ()))); } privat datoformatDato (objektværdi) {prøv {returformat (værdi.getAsString ()); } fange (ParseException ex) {smid ny JsonParseException (ex); }}} 

Nu skal vi registrere det i GsonBuilder mod vores måltype Kort> og opbyg en skræddersyet Gson objekt.

Når vi kalder fraJson API om dette Gson objekt, parseren påkalder den brugerdefinerede deserializer og returnerer det ønskede Kort eksempel:

String jsonString = "{'Bob': '2017-06-01', 'Jennie': '2015-01-03'}"; Type type = ny TypeToken() {}. getType (); Gson gson = ny GsonBuilder () .registerTypeAdapter (type, ny StringDateMapDeserializer ()) .create (); Kort empJoiningDateMap = gson.fromJson (jsonString, type); Assert.assertEquals (2, empJoiningDateMap.size ()); Assert.assertEquals (Date.class, empJoiningDateMap.get ("Bob"). GetClass ()); 

Denne taktik er også nyttig, når vores kort kan indeholde heterogene værdier, og vi har en god idé om, hvor mange forskellige typer værdier der kunne være der.

For at lære mere om en brugerdefineret deserializer i Gson, er du velkommen til at gennemgå Gson Deserialization Cookbook.

5. Konklusion

I denne korte artikel lærte vi flere måder at konstruere et kort ud fra en JSON-formateret streng. Og vi diskuterede også ordentlige brugssager til disse variationer.

Kildekoden til eksemplerne er tilgængelig på GitHub.