How can I convert JSON to a HashMap using Gson?

前端 未结 16 2348
臣服心动
臣服心动 2020-11-22 05:14

I\'m requesting data from a server which returns data in the JSON format. Casting a HashMap into JSON when making the request wasn\'t hard at all but the other way seems to

相关标签:
16条回答
  • 2020-11-22 05:52
     HashMap<String, String> jsonToMap(String JsonDetectionString) throws JSONException {
    
        HashMap<String, String> map = new HashMap<String, String>();
        Gson gson = new Gson();
    
        map = (HashMap<String, String>) gson.fromJson(JsonDetectionString, map.getClass());
    
        return map;
    
    }
    
    0 讨论(0)
  • 2020-11-22 05:53

    Here's a one-liner that will do it:

    HashMap<String, Object> myMap =
       gson.fromJson(yourJson, new TypeToken<HashMap<String, Object>>(){}.getType());
    
    0 讨论(0)
  • 2020-11-22 05:53

    This is more of addendum to Kevin Dolan's answer than a complete answer, but I was having trouble extracting the type from the Number. This is my solution:

    private Object handlePrimitive(JsonPrimitive json) {
      if(json.isBoolean()) {
        return json.getAsBoolean();
      } else if(json.isString())
        return json.getAsString();
      }
    
      Number num = element.getAsNumber();
    
      if(num instanceof Integer){
        map.put(fieldName, num.intValue());
      } else if(num instanceof Long){
        map.put(fieldName, num.longValue());
      } else if(num instanceof Float){
        map.put(fieldName, num.floatValue());
      } else {    // Double
         map.put(fieldName, num.doubleValue());
      }
    }
    
    0 讨论(0)
  • 2020-11-22 05:56

    Update for new Gson lib:
    You now can parse nested Json to Map directly, but you should be aware in case you try to parse Json to Map<String, Object> type: it will raise exception. To fix this, just declare the result as LinkedTreeMap type. Example below:

    String nestedJSON = "{"id":"1","message":"web_didload","content":{"success":1}};
    Gson gson = new Gson();
    LinkedTreeMap result = gson.fromJson(nestedJSON , LinkedTreeMap.class);
    
    0 讨论(0)
  • 2020-11-22 05:57

    Try this, it will worked. I used it for Hashtable.

    public static Hashtable<Integer, KioskStatusResource> parseModifued(String json) {
        JsonObject object = (JsonObject) new com.google.gson.JsonParser().parse(json);
        Set<Map.Entry<String, JsonElement>> set = object.entrySet();
        Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();
    
        Hashtable<Integer, KioskStatusResource> map = new Hashtable<Integer, KioskStatusResource>();
    
        while (iterator.hasNext()) {
            Map.Entry<String, JsonElement> entry = iterator.next();
    
            Integer key = Integer.parseInt(entry.getKey());
            KioskStatusResource value = new Gson().fromJson(entry.getValue(), KioskStatusResource.class);
    
            if (value != null) {
                map.put(key, value);
            }
    
        }
        return map;
    }
    

    Replace KioskStatusResource to your class and Integer to your key class.

    0 讨论(0)
  • 2020-11-22 05:58

    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...

    0 讨论(0)
提交回复
热议问题