Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Convertir json a objeto Map.Entry con Gson

VERSIÓN FÁCIL

Si le pido a Gson que convierta algún json válido en MyMap no tiene ningún problema para hacerlo

public class MyMap{ Map<Long,String> content; } MyMap myMap = gson.fromJson(json, new TypeToken<MyMap>() {}.getType()); 

VERSIÓN DIFÍCIL:

¿Cómo obtengo que Gson haga lo siguiente?

 public class MyDS{ Map<Map.Entry<Long,String>,Map<Long,String>> content; } MyDS myDS = gson.fromJson(json, new TypeToken<MyDS>() {}.getType()); 

Ejemplo json si realmente lo necesita.

 "content": { "[1, dog]": { "1": "max", "2": "pi", "3": "robot", "4": "catcher", "5": "reaper" }, "[2, cat]": { "6": "black", "7": "white", "8": "meow", "9": "mice", "10": "rat" }, "[3, rabbit]": { "16": "bunny", "17": "ears", "28": "burgerbun", "39": "alice", "50": "tweak" } } 

Más notas

Para una buena medida, intento ejecutar una prueba de unidad donde todo lo que hago es intentar leer el json con Gson, y consigo el rastro del error siguiente:

 at sun.misc.Unsafe.allocateInstance(Native method) java.lang.reflect.Method.invoke!(Native method) com.google.gson.internal.UnsafeAllocator$1.newInstance(UnsafeAllocator.java:48) com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:223) com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:207) com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:186) com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145) com.google.gson.Gson.fromJson(Gson.java:861) com.google.gson.Gson.fromJson(Gson.java:826) com.google.gson.Gson.fromJson(Gson.java:775) 

No importa si las teclas son de la forma "[3, rabbit]" para "{3, rabbit}"

  • Servicio web SOAP y JSON responce en android
  • ¿Está bien para guardar una matriz JSON en SharedPreferences?
  • Crear json en android
  • Crear cadena JSON con GSON
  • No se puede deserializar la instancia del objeto de START_ARRAY token en Spring Webservice
  • Android: Convertir secuencia a cadena sin quedarse sin memoria
  • Cómo analizar con GSON cuando el identificador tiene espacio en el nombre
  • Respuesta HTML desde el servidor
  • 2 Solutions collect form web for “Convertir json a objeto Map.Entry con Gson”

    Suponiendo que tiene un contenido JSON válido del tipo:

     { "content": { "[1, dog]": { "1": "max", "2": "pi", "3": "robot", "4": "catcher", "5": "reaper" }, "[2, cat]": { "6": "black", "7": "white", "8": "meow", "9": "mice", "10": "rat" }, "[3, rabbit]": { "16": "bunny", "17": "ears", "28": "burgerbun", "39": "alice", "50": "tweak" } } } 

    Para lograr lo que quieres, simplemente puedes implementar tu propio Map.Entry Deserializer ya que no se puede deserializar fuera de la caja porque no es una matriz y {3, rabbit} no es un objeto JSON válido.

    Así que su Deserializer podría confiar en una expresión regular para extraer la clave y el valor a continuación, crear una instancia de AbstractMap.SimpleEntry utilizando los valores extraídos, algo así como:

     public class MapEntryDeserializer implements JsonDeserializer<Map.Entry<Long, String>> { /** * Pattern corresponding to: * Starts with [ * <a non empty sequence of digit characters>, * <a non empty sequence of any characters * Ends with ] */ private static final Pattern PATTERN = Pattern.compile("^\\[(\\d+), ?(.+)\\]$"); public Map.Entry<Long, String> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { // Extract the key/value pair from Strings of type [3, rabbit] String value = json.getAsString(); Matcher matcher = PATTERN.matcher(value); if (!matcher.find()) { throw new JsonParseException( String.format("The map entry doesn't have the expected format: %s", value) ); } return new AbstractMap.SimpleEntry<>( Long.valueOf(matcher.group(1)), matcher.group(2) ); } } 

    Entonces puedo deserializar mi contenido de JSON con:

     Type type = new TypeToken<MyDS>() {}.getType(); Gson gson = new GsonBuilder() .registerTypeAdapter(Map.Entry.class, new MapEntryDeserializer()) .create(); MyDS myDS = gson.fromJson(json, type); 

    Según la documentación de Map.Entry:

    La única manera de obtener una referencia a una entrada de mapa es del iterador de esta vista de colección.

    https://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html

    Esto significa que no puede obtener Map.Entry hasta que haya creado el Mapa inicial. Para lograr lo que quieres, necesitas analizar el JSON en un Mapa, luego iterar sobre él para insertarlo en tu objeto MyDS.

    Dicho esto, dependiendo de su uso final, podría haber mejores formas de reorganizar / introducir los datos después de analizarlos.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.