Saltar al contenido

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

Posteriormente a investigar con especialistas en este tema, programadores de deferentes áreas y profesores dimos con la solución al problema y la compartimos en este post.

Solución:

Aquí tienes:

import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;

Type type = new TypeToken>().getType();
Map myMap = gson.fromJson("'k1':'apple','k2':'orange'", type);

Este código funciona:

Gson gson = new Gson(); 
String json = ""k1":"v1","k2":"v2"";
Map map = new HashMap();
map = (Map) gson.fromJson(json, map.getClass());

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

La forma en que funciona mi deserializador yaml, por defecto los objetos JSON son Map cuando no especifica un tipo, pero gson no parece hacer esto. Afortunadamente, puede lograrlo con un deserializador personalizado.

Usé el siguiente deserializador para deserializar naturalmente cualquier cosa, por defecto JsonObjects a Map y JsonArrays a Object[]s, donde todos los elementos secundarios se deserializan de manera similar.

private static class NaturalDeserializer implements JsonDeserializer 
  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 map = new HashMap();
    for(Map.Entry entry : json.entrySet())
      map.put(entry.getKey(), context.deserialize(entry.getValue(), Object.class));
    return map;
  


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

Puede 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…

Reseñas y valoraciones

Agradecemos que quieras añadir valor a nuestro contenido añadiendo tu veteranía en las interpretaciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Respuestas a preguntas comunes sobre programacion y tecnología