How can I convert JSON to a HashMap using Gson? How can I convert JSON to a HashMap using Gson? json json

How can I convert JSON to a HashMap using Gson?


Here you go:

import java.lang.reflect.Type;import com.google.gson.reflect.TypeToken;Type type = new TypeToken<Map<String, String>>(){}.getType();Map<String, String> myMap = gson.fromJson("{'k1':'apple','k2':'orange'}", type);


This code works:

Gson gson = new Gson(); String json = "{\"k1\":\"v1\",\"k2\":\"v2\"}";Map<String,Object> map = new HashMap<String,Object>();map = (Map<String,Object>) gson.fromJson(json, map.getClass());


I know this is a fairly old question, but I was searching for a solution to generically deserialize nested JSON to a Map<String, Object>, and found nothing.

The way my yaml deserializer works, it defaults JSON objects to Map<String, Object> when you don't specify a type, but gson doesn't seem to do this. Luckily you can accomplish it with a custom deserializer.

I used the following deserializer to naturally deserialize anything, defaulting JsonObjects to Map<String, Object> and JsonArrays to Object[]s, where all the children are similarly deserialized.

private static class NaturalDeserializer implements JsonDeserializer<Object> {  public Object deserialize(JsonElement json, Type typeOfT,       JsonDeserializationContext context) {    if(json.isJsonNull()) return null;    else if(json.isJsonPrimitive()) return handlePrimitive(json.getAsJsonPrimitive());    else if(json.isJsonArray()) return handleArray(json.getAsJsonArray(), context);    else return handleObject(json.getAsJsonObject(), context);  }  private Object handlePrimitive(JsonPrimitive json) {    if(json.isBoolean())      return json.getAsBoolean();    else if(json.isString())      return json.getAsString();    else {      BigDecimal bigDec = json.getAsBigDecimal();      // Find out if it is an int type      try {        bigDec.toBigIntegerExact();        try { return bigDec.intValueExact(); }        catch(ArithmeticException e) {}        return bigDec.longValue();      } catch(ArithmeticException e) {}      // Just return it as a double      return bigDec.doubleValue();    }  }  private Object handleArray(JsonArray json, JsonDeserializationContext context) {    Object[] array = new Object[json.size()];    for(int i = 0; i < array.length; i++)      array[i] = context.deserialize(json.get(i), Object.class);    return array;  }  private Object handleObject(JsonObject json, JsonDeserializationContext context) {    Map<String, Object> map = new HashMap<String, Object>();    for(Map.Entry<String, JsonElement> entry : json.entrySet())      map.put(entry.getKey(), context.deserialize(entry.getValue(), Object.class));    return map;  }}

The messiness inside the handlePrimitive method is for making sure you only ever get a Double or an Integer or a Long, and probably could be better, or at least simplified if you're okay with getting BigDecimals, which I believe is the default.

You can register this adapter like:

GsonBuilder gsonBuilder = new GsonBuilder();gsonBuilder.registerTypeAdapter(Object.class, new NaturalDeserializer());Gson gson = gsonBuilder.create();

And then call it like:

Object natural = gson.fromJson(source, Object.class);

I'm not sure why this is not the default behavior in gson, since it is in most other semi-structured serialization libraries...