fromjson java json dictionary hashmap gson

java - fromjson - ¿Cómo puedo convertir JSON a HashMap usando Gson?



gson java (16)

Abajo esta soportado desde gson 2.8.0

public static Type getMapType(Class keyType, Class valueType){ return TypeToken.getParameterized(HashMap.class, keyType, valueType).getType(); } public static <K,V> HashMap<K,V> fromMap(String json, Class<K> keyType, Class<V> valueType){ return gson.fromJson(json, getMapType(keyType,valueType)); }

Solicito datos de un servidor que devuelve datos en formato JSON. Convertir un HashMap en JSON cuando se realizó la solicitud no fue difícil en absoluto, pero la otra manera parece ser un poco difícil. La respuesta de JSON se ve así:

{ "header" : { "alerts" : [ { "AlertID" : "2", "TSExpires" : null, "Target" : "1", "Text" : "woot", "Type" : "1" }, { "AlertID" : "3", "TSExpires" : null, "Target" : "1", "Text" : "woot", "Type" : "1" } ], "session" : "0bc8d0835f93ac3ebbf11560b2c5be9a" }, "result" : "4be26bc400d3c" }

¿De qué manera sería más fácil acceder a estos datos? Estoy usando el módulo GSON.


Actualización para la nueva versión de Gson:
Ahora puede analizar Json anidado para asignar directamente, pero debe tener en cuenta en caso de que intente analizar Json para asignar tipo Map<String, Object> : generará una excepción. Para solucionar este problema, simplemente declare el resultado como tipo LinkedTreeMap . Ejemplo a continuación:

String nestedJSON = "{"id":"1","message":"web_didload","content":{"success":1}}; Gson gson = new Gson(); LinkedTreeMap result = gson.fromJson(nestedJSON , LinkedTreeMap.class);


Aquí hay una sola línea que lo hará:

HashMap<String, Object> myMap = gson.fromJson(yourJson, new TypeToken<HashMap<String, Object>>(){}.getType());


Aqui tienes:

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);


Con Gson 2.7 de Google (probablemente versiones anteriores también, pero probé con la versión actual 2.7) es tan simple como:

Map map = gson.fromJson(jsonString, Map.class);

Lo que devuelve un Map de tipo com.google.gson.internal.LinkedTreeMap y funciona recursivamente en objetos anidados, matrices, etc.

Ejecuté el ejemplo de OP como tal (simplemente reemplazé las comillas dobles con espacios en blanco y eliminé los espacios en blanco):

String jsonString = "{''header'': {''alerts'': [{''AlertID'': ''2'', ''TSExpires'': null, ''Target'': ''1'', ''Text'': ''woot'', ''Type'': ''1''}, {''AlertID'': ''3'', ''TSExpires'': null, ''Target'': ''1'', ''Text'': ''woot'', ''Type'': ''1''}], ''session'': ''0bc8d0835f93ac3ebbf11560b2c5be9a''}, ''result'': ''4be26bc400d3c''}"; Map map = gson.fromJson(jsonString, Map.class); System.out.println(map.getClass().toString()); System.out.println(map);

Y consiguió la siguiente salida:

class com.google.gson.internal.LinkedTreeMap {header={alerts=[{AlertID=2, TSExpires=null, Target=1, Text=woot, Type=1}, {AlertID=3, TSExpires=null, Target=1, Text=woot, Type=1}], session=0bc8d0835f93ac3ebbf11560b2c5be9a}, result=4be26bc400d3c}


Este código funciona:

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());


Esto es lo que he estado usando:

public static HashMap<String, Object> parse(String json) { JsonObject object = (JsonObject) parser.parse(json); Set<Map.Entry<String, JsonElement>> set = object.entrySet(); Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator(); HashMap<String, Object> map = new HashMap<String, Object>(); while (iterator.hasNext()) { Map.Entry<String, JsonElement> entry = iterator.next(); String key = entry.getKey(); JsonElement value = entry.getValue(); if (!value.isJsonPrimitive()) { map.put(key, parse(value.toString())); } else { map.put(key, value.getAsString()); } } return map; }


Esto es más una adición a la respuesta de Kevin Dolan que una respuesta completa, pero estaba teniendo problemas para extraer el tipo del Número. Esta es mi solución:

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()); } }


He superado un problema similar con un JsonDeSerializer personalizado. Traté de hacerlo un poco genérico, pero aún no es suficiente. Aunque es una solución que se ajusta a mis necesidades.

En primer lugar, necesita implementar un nuevo JsonDeserializer para objetos de mapa.

public class MapDeserializer<T, U> implements JsonDeserializer<Map<T, U>>

Y el método de deserialización se verá similar a esto:

public Map<T, U> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (!json.isJsonObject()) { return null; } JsonObject jsonObject = json.getAsJsonObject(); Set<Entry<String, JsonElement>> jsonEntrySet = jsonObject.entrySet(); Map<T, U> deserializedMap = new HashMap<T, U>(); for (Entry<java.lang.String, JsonElement> entry : jsonEntrySet) { try { U value = context.deserialize(entry.getValue(), getMyType()); deserializedMap.put((T) entry.getKey(), value); } catch (Exception ex) { logger.info("Could not deserialize map.", ex); } } return deserializedMap; }

La contra con esta solución, es que la clave de mi Mapa es siempre de Tipo "Cadena". Sin embargo, al cambiar algunas cosas, alguien puede hacer que sea genérico. Además, debo decir que la clase del valor debe pasarse en el constructor. Por lo tanto, el método getMyType() en mi código devuelve el tipo de los valores del Mapa, que se pasó en el constructor.

Puede consultar esta publicación. ¿Cómo escribo un deserializador JSON personalizado para Gson? con el fin de aprender más sobre deserializadores personalizados.


Intenta esto, funcionará. Lo usé para 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; }

Reemplace KioskStatusResource a su clase e Integer a su clase clave.


JSONObject normalmente utiliza HashMap internamente para almacenar los datos. Entonces, puedes usarlo como Mapa en tu código.

Ejemplo,

JSONObject obj = JSONObject.fromObject(strRepresentation); Iterator i = obj.entrySet().iterator(); while (i.hasNext()) { Map.Entry e = (Map.Entry)i.next(); System.out.println("Key: " + e.getKey()); System.out.println("Value: " + e.getValue()); }


Sé que esta es una pregunta bastante antigua, pero estaba buscando una solución para deserializar genéricamente JSON anidado a un Map<String, Object> , y no encontré nada.

La forma en que funciona el deserializador de yaml hace que los objetos JSON predeterminados se asignen a Map<String, Object> cuando no se especifica un tipo, pero gson no parece hacer esto. Afortunadamente, puedes lograrlo con un deserializador personalizado.

Utilicé el siguiente deserializador para deserializar de forma natural cualquier cosa, de forma JsonObject s Map<String, Object> y JsonArray s to Object[] s, donde todos los elementos JsonArray están deserializados de manera similar.

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; } }

El desorden dentro del método handlePrimitive es para asegurarse de que solo obtenga un Double o un Integer o un Long, y probablemente podría ser mejor, o al menos simplificado si está de acuerdo con obtener BigDecimals, que creo que es el valor predeterminado.

Puedes registrar este adaptador como:

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

Y luego llámalo como:

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

No estoy seguro de por qué este no es el comportamiento predeterminado en gson, ya que está en la mayoría de las otras bibliotecas de serialización semiestructuradas ...


Tuve exactamente la misma pregunta y terminé aquí. Tenía un enfoque diferente que parece mucho más simple (¿quizás versiones más nuevas de gson?).

Gson gson = new Gson(); Map jsonObject = (Map) gson.fromJson(data, Object.class);

con el siguiente json

{ "map-00": { "array-00": [ "entry-00", "entry-01" ], "value": "entry-02" } }

El seguimiento

Map map00 = (Map) jsonObject.get("map-00"); List array00 = (List) map00.get("array-00"); String value = (String) map00.get("value"); for (int i = 0; i < array00.size(); i++) { System.out.println("map-00.array-00[" + i + "]= " + array00.get(i)); } System.out.println("map-00.value = " + value);

salidas

map-00.array-00[0]= entry-00 map-00.array-00[1]= entry-01 map-00.value = entry-02

Puede verificar dinámicamente usando instanceof al navegar por su jsonObject. Algo como

Map json = gson.fromJson(data, Object.class); if(json.get("field") instanceof Map) { Map field = (Map)json.get("field"); } else if (json.get("field") instanceof List) { List field = (List)json.get("field"); } ...

Funciona para mí, por lo que debe funcionar para ti ;-)


Utilicé este código:

Gson gson = new Gson(); HashMap<String, Object> fields = gson.fromJson(json, HashMap.class);


Puedes usar esta clase en su lugar :) (maneja incluso listas, listas anidadas y json)

public class Utility { public static Map<String, Object> jsonToMap(Object json) throws JSONException { if(json instanceof JSONObject) return _jsonToMap_((JSONObject)json) ; else if (json instanceof String) { JSONObject jsonObject = new JSONObject((String)json) ; return _jsonToMap_(jsonObject) ; } return null ; } private static Map<String, Object> _jsonToMap_(JSONObject json) throws JSONException { Map<String, Object> retMap = new HashMap<String, Object>(); if(json != JSONObject.NULL) { retMap = toMap(json); } return retMap; } private static Map<String, Object> toMap(JSONObject object) throws JSONException { Map<String, Object> map = new HashMap<String, Object>(); Iterator<String> keysItr = object.keys(); while(keysItr.hasNext()) { String key = keysItr.next(); Object value = object.get(key); if(value instanceof JSONArray) { value = toList((JSONArray) value); } else if(value instanceof JSONObject) { value = toMap((JSONObject) value); } map.put(key, value); } return map; } public static List<Object> toList(JSONArray array) throws JSONException { List<Object> list = new ArrayList<Object>(); for(int i = 0; i < array.length(); i++) { Object value = array.get(i); if(value instanceof JSONArray) { value = toList((JSONArray) value); } else if(value instanceof JSONObject) { value = toMap((JSONObject) value); } list.add(value); } return list; } }

Para convertir su cadena JSON a hashmap use esto:

HashMap<String, Object> hashMap = new HashMap<>(Utility.jsonToMap(response)) ;


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; }