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

  • Gson - convierta de Json a una clase ArrayList <T>
  • Reemplazar el analizador estándar de Android JSON para un mejor rendimiento?
  • Cómo analizar este JSON Array en android
  • JacksonParser databind y la causa principal "Encontró archivo duplicado para APK"?
  • Cargando JSON de String en JSONArray en Android
  • Cómo analizar el análisis de json Usando GSON en android
  • 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}"

  • "Unparseable date: 1302828677828" intentando deserializar con Gson una fecha de formato milisegundo recibida del servidor
  • Gson y Active Android: Se ha intentado serializar java.lang.Class. ¿Has olvidado registrar un adaptador de tipo?
  • Analiza el formato de fecha de JSON en String usando GSON en Android
  • GSON: Serializar un único campo nulo sin utilizar el serializeNulls global ()
  • Android JSON CharSet UTF-8 problemas
  • JSONException: El valor del tipo java.lang.String no se puede convertir en JSONObject
  • 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.