java gwt gson

java - Análisis de JSON Mapa de mapas con GSON



gwt (1)

Lo he intentado todo, pero la solución es muy fea, realmente quiero una respuesta directa si esto se puede mejorar (y eso significa que si necesito usar una implementación diferente).

El problema radica en el Mapa de mapas con GSON:

Me da esta respuesta de acuerdo con Firebug:

{"id": 2, "result": {"FirstWorld": {"FirstValue": 5, ... }, "SecondWorld":{"FirstValue": 5, ....}}, "error":null }

Hay alrededor de 200 "Values" , pero solo dos "Worlds" . Esto es lo que tengo hasta ahora para analizarlo en mi clase ControlService :

public void RegisterValues( String [] Names, AsyncCallback<Map<String,RegisterValues>> callback); public class RegisterValues { int FirstValue; int SecondValue; ... And so on 200 times !!!

Así que accedo a los datos así:

service_.RegisterValues( Names, new AsyncCallback<ControlService.RegisterValues>() { public void onSuccess( GlibControlService.RegisterValues result ) { String test = "FirstValue"; String message="Result for channel 1 is "; for( String Name : result.keySet() ) message+=Name+"="+result.get(Name);

Pero como pueden ver, esto va a ser realmente largo. El otro problema es que algunos de los "valores" tienen ampersands en ellos, lo que significa que no puedo usarlos en este método;

@SerializedName("One&Two") // Ampersand not allowed in name int OneTwo; //gives Invalid JSON response apparently

¿Alguien tiene un mejor método para hacer esto?

EDITAR código que funciona:

private ControlService service_; service_.connectedNames( new String[0], new AsyncCallback<String[]>() { public void onSuccess( String[] result) { List_.removeItem(0); Names = result; for( String Name : result ) { List_.addItem(Name); } List_.setEnabled( true ); } public void onFailure(Throwable why) { List_.removeItem(0); List_.addItem( "Server error!" ); } });

Luego, en mi clase ControlService, tengo esto:

@RpcImpl(version=RpcImpl.Version.V2_0,transport=RpcImpl.Transport.HTTP_POST) public interface ControlService extends RemoteJsonService { public void connectedNames( String [] Names, AsyncCallback<String[]> callback );

Esto funciona perfectamente

Intenté hacerlo de manera muy similar agregando esto en mi ControlService:

public void RegisterValues( String [] Names, AsyncCallback<Map< String,Map<String, Integer>> callback);

Y así sucesivamente, asegurándose de que el Map<String, Map<String, Integer>> también estaba en la parte onSucess() de la estructura. Sin embargo, esto causó que mi programa fallara. Me pareció que no le gustan los mapas anidados. Sin embargo, GSON analizará automáticamente los objetos si el nombre del miembro coincide con el campo JSON. Así que usé ese RegisterValues para obligar automáticamente a GSON a analizar esto.

Stack trace:

[ERROR] Errors in ''generated://AF9BA58B045D92E7896CD657C9CC5FAF/example/client/ControlService_JsonProxy.java'' [ERROR] Line 18: INSTANCE cannot be resolved or is not a field See snapshot: /var/folders/pf/56b3mznn35gg741rlsqq424m0000gp/T/example.client.ControlService_JsonProxy2948240672238331252.java

Esta es la razón por la que creo que GSON no puede analizar automáticamente los mapas anidados usando AsyncCallback. Puede ser mejor hacer mi llamada HTTP más en línea con lo que sugiere a continuación.


La mejor manera es ajustar la respuesta que publicó en una clase.

{"id": 2, "result": {"FirstWorld": {"FirstValue": 5, ... }, "SecondWorld":{"FirstValue": 5, ....}}, "error":null }

import java.util.Map; public class Response { private int id; private Map<String, Map<String, Integer>> result; private String error; public int getId() { return id; } public void setId(int id) { this.id = id; } public Map<String, Map<String, Integer>> getResult() { return result; } public void setResult(Map<String, Map<String, Integer>> result) { this.result = result; } public String getError() { return error; } public void setError(String error) { this.error = error; } }

He probado con esto y funciona bien.

static String json = "{/"id/":2,/"result/":{/"FirstWorld/":{/"FirstValue/":5,/"SecondValue/":6},/"SecondWorld/":{/"FirstValue/":5,/"SecondValue/":6}},/"error/":null}"; public static void main(String[] args) { Gson g= new Gson(); Response b=g.fromJson(json, Response.class ); System.out.println(g.toJson(b)); }

Si necesita declarar la clase RegisterValues , solo necesita reemplazar el Map<String, Integer> del resultado con esta clase, probablemente extendiendo Map .