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

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.

  • ¿Debo usar XML o JSON como un formato de datos en las aplicaciones de Android?
  • ¿Cómo puedo eliminar un elemento específico de un JSONArray?
  • crear Json desde sqlite en Android
  • Parsing marco que se ocupa bien de referencias circulares en JSON
  • ¿Está google gson funcionando en android?
  • Uso de Gson para analizar la matriz y el objeto Json sin nombre
  • Http Get Request devuelve html?
  • El inicio de Backend para móviles subscribeToCloudMessage no funcionará
  • ¿Pueden las anotaciones de Gson y Jackson coexistir en el mismo POJO?
  • No conseguir el pulgar con géneros - jugador de música universal
  • Android: Se ha intentado serializar ... ¿Ha olvidado registrar un adaptador de tipo? "
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.