Preveďte JSON na mapu pomocou Gson

1. Úvod

V tomto rýchlom výučbe sa naučíme, ako previesť reťazec JSON na formát Mapa použitím Gson od spoločnosti Google.

Uvidíme tri rôzne prístupy, ako to dosiahnuť, a prediskutujeme ich klady a zápory - na niekoľkých praktických príkladoch.

2. Prihrávka Mapa.trieda

Všeobecne, Gson poskytuje nasledujúce API vo svojom Gson triedy na prevod reťazca JSON na objekt:

public T fromJson (String json, Class classOfT) hodí JsonSyntaxException;

Z podpisu je zrejmé, že druhým parametrom je trieda objektu, do ktorej chceme analyzovať JSON. V našom prípade by malo byť Mapa.trieda:

Reťazec jsonString = "{'employee.name': 'Bob', 'employee.salary': 10 000}"; Gson gson = nový Gson (); Mapa mapa = gson.fromJson (jsonString, Map.class); Assert.assertEquals (2, map.size ()); Assert.assertEquals (Double.class, map.get ("employee.salary"). GetClass ());

Tento prístup urobí najlepší odhad, pokiaľ ide o typ hodnoty pre každú vlastnosť.

Napríklad budú vynútené čísla Dvojitýs, pravda a nepravdivé do Boolovskýa predmety do LinkedTreeMaps.

Ak však existujú duplicitné kľúče, nátlak zlyhá a vyhodí a JsonSyntaxException.

A kvôli vymazanie typu, nebudeme môcť nakonfigurovať ani toto nátlakové správanie. Ak teda potrebujeme špecifikovať typy kľúčov alebo hodnôt, budeme potrebovať iný prístup.

3. Používanie TypeToken

Na prekonanie problému vymazania typov pre generické typy, Gson má preťaženú verziu API:

public T fromJson (String json, Type typeOfT) hodí JsonSyntaxException;

Môžeme zostrojiť a Mapa s typovými parametrami pomocou Gson TypeToken. The TypeToken trieda vráti inštanciu ParameterizedTypeImpl ktorý zachováva typ kľúča a hodnotu aj za behu programu:

String jsonString = "{'Bob': {'name': 'Bob Willis'}," + "'Jenny': {'name': 'Jenny McCarthy'}," + "'Steve': {'name': 'Steven Waugh'}} "; Gson gson = nový Gson (); Typ empMapType = nový TypeToken() {} .getType (); Názov mapyEmployeeMap = gson.fromJson (jsonString, empMapType); Assert.assertEquals (3, nameEmployeeMap.size ()); Assert.assertEquals (Employee.class, nameEmployeeMap.get ("Bob"). GetClass ()); 

Teraz, ak zostrojíme svoje Mapa typ ako Mapa, potom bude analyzátor stále predvolený, ako sme videli v predchádzajúcej časti.

Samozrejme to stále prináleží Gsonovi za vynútenie primitívnych typov. Aj tie je však možné prispôsobiť.

4. Používanie možnosti Vlastné JsonDeserializer

Keď potrebujeme jemnozrnnú kontrolu nad stavbou nášho Mapa objektu, môžeme implementovať vlastný deserializátor typu JsonDeserializer.

Ak si chcete pozrieť príklad, predpokladajme, že náš JSON obsahuje meno zamestnanca ako kľúč a jeho dátum prijatia ako jeho hodnotu. Ďalej predpokladajme, že formát dátumu je rrrr / MM / dd, ktorý nie je štandardným formátom pre Gson.

Môžeme nakonfigurovať Gson tak, aby našu mapu analyzoval inak, a to implementáciou a JsonDeserializer:

verejná trieda StringDateMapDeserializer implementuje JsonDeserializer {private SimpleDateFormat format = new SimpleDateFormat ("yyyy / MM / dd"); @Override public Map deserialize (prvok JsonElement, typ typu, JsonDeserializationContext jsonDeserializationContext) {return elem.getAsJsonObject () .entrySet () .stream () .filter (e -> e.getValue (). IsJsonPrimitive ()) -> e.getValue (). getAsJsonPrimitive (). isString ()) .collect (Collectors.toMap (Map.Entry :: getKey, e -> formatDate (e.getValue ()))); } súkromné ​​Dátum formatDate (hodnota objektu) {try {return format (value.getAsString ()); } catch (ParseException ex) {throw new JsonParseException (ex); }}} 

Teraz to musíme zaregistrovať v GsonBuilder oproti nášmu cieľovému typu Mapa> a vytvoriť prispôsobené Gson objekt.

Keď hovoríme odJsona API na toto Gson objekt, syntaktický analyzátor vyvolá vlastný deserializátor a vráti požadovaný Mapa inštancia:

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

Táto taktika je tiež užitočná, keď naša mapa môže obsahovať heterogénne hodnoty a máme reálnu predstavu o tom, koľko rôznych typov hodnôt by tam mohlo byť.

Ak sa chcete dozvedieť viac o vlastnom deserializéri v Gson, kľudne si choďte prečítať kuchársku knihu deserializácie Gson.

5. Záver

V tomto krátkom článku sme sa naučili niekoľko spôsobov, ako zostaviť mapu z reťazca vo formáte JSON. A tiež sme diskutovali o správnych prípadoch použitia týchto variácií.

Zdrojový kód príkladov je k dispozícii na serveri GitHub.