Konverter JSON til et kart ved hjelp av Gson

1. Introduksjon

I denne raske opplæringen lærer vi hvordan vi konverterer en JSON-streng til en Kart ved hjelp av Gson fra Google.

Vi får se tre forskjellige tilnærminger for å oppnå det og diskutere fordeler og ulemper med noen praktiske eksempler.

2. Bestått Map.class

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

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

Fra signaturen er det veldig klart at den andre parameteren er klassen til objektet som vi vil JSON analysere. I vårt tilfelle burde det være det Map.class:

String jsonString = "{'medarbeider.navn': 'Bob', 'ansatt.lønn': 10000}"; Gson gson = ny Gson (); Kartkart = gson.fromJson (jsonString, Map.class); Assert.assertEquals (2, map.size ()); Assert.assertEquals (Double.class, map.get ("ansatt.lønn"). GetClass ());

Denne tilnærmingen vil gi sitt beste gjetning angående verditype for hver eiendom.

For eksempel vil tall bli tvunget inn Dobbelts, ekte og falsk inn i Boolskog gjenstander inn i LinkedTreeMaps.

Hvis det er dupliserte nøkler, vil tvang imidlertid mislykkes og det vil kaste et JsonSyntaxException.

Og på grunn av sletting, vi vil heller ikke kunne konfigurere denne tvangsatferden. Så hvis vi trenger å spesifisere nøkkel- eller verdityper, trenger vi en annen tilnærming.

3. Bruke TypeToken

For å overvinne problemet med typesletting for generiske typer, Gson har en overbelastet versjon av API:

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

Vi kan konstruere en Kart med typeparametere ved hjelp av Gson's TypeToken. De TypeToken klasse returnerer en forekomst av ParameterizedTypeImpl som bevarer nøkkeltypen og verdien selv ved kjøretid:

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

Nå, hvis vi konstruerer vår Kart skriv inn som Kart, så vil parseren fortsatt være standard som vi så i forrige avsnitt.

Selvfølgelig faller dette fortsatt tilbake til Gson for å tvinge primitive typer. Disse kan imidlertid også tilpasses.

4. Bruke egendefinert JsonDeserializer

Når vi trenger finkornet kontroll over konstruksjonen av vår Kart objekt, kan vi implementere en tilpasset deserializer av typen JsonDeserializer.

For å se et eksempel, la oss anta at vår JSON inneholder ansattens navn som nøkkel og ansettelsesdatoen som verdi. La oss anta at datoformatet er åååå / MM / dd, som ikke er et standardformat for Gson.

Vi kan konfigurere Gson til å analysere kartet vårt annerledes ved å implementere et JsonDeserializer:

offentlig klasse StringDateMapDeserializer implementerer JsonDeserializer {private SimpleDateFormat format = ny 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 ()))); } private Date formatDate (Object value) {try {return format (value.getAsString ()); } catch (ParseException ex) {throw new JsonParseException (ex); }}} 

Nå må vi registrere det i GsonBuilder mot vår måltype Kart> og bygg en tilpasset Gson gjenstand.

Når vi kaller fraJson API på dette Gson objektet, påkaller parseren den egendefinerte deserialisatoren og returnerer ønsket Kart forekomst:

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

Denne taktikken er også nyttig når kartet vårt kan inneholde heterogene verdier, og vi har en god ide om hvor mange forskjellige verdityper som kan være der.

For å lære mer om en tilpasset deserializer i Gson, gå gjerne gjennom Gson Deserialization Cookbook.

5. Konklusjon

I denne korte artikkelen lærte vi flere måter å konstruere et kart fra en JSON-formatert streng. Og vi diskuterte også riktig brukstilfelle for disse variasjonene.

Kildekoden for eksemplene er tilgjengelig på GitHub.


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