libreria ejemplo java json rest gson retrofit2

java - ejemplo - ¿Cómo analizar la lista de objetos JSON rodeados por[] usando Retrofit y GSON?



libreria gson java (3)

El hecho curioso es ... Mi código está perfectamente bien. Al menos la presentada en la pregunta anterior.

Terminé eliminando una línea de mi modelo Size .

Como me enfoqué en el código en sí (especialmente en la configuración de Retrofit), ignoré totalmente las importaciones.

Resultó que, al implementar el modelo Size cuando comencé a escribir String clase String para los campos del modelo:

  • name
  • createdAt
  • updatedAt

La finalización del código de IntelliJ IDEA me sugirió

  • no java.lang.String
  • pero com.sun.org.apache.xpath.internal.operations.String

Lo que desordenó totalmente la deserialización de Gson .

Cuando se trata de recompensas ...

He decidido marcar como válida mi propia respuesta. ¿Por qué?

  • Para garantizar eso, cada uno de esos desarrolladores, que vendrán con los mismos problemas que yo, asegúrese de tener importaciones válidas .

Muchas gracias a los caballeros de arriba por sus excelentes servicios.

Como solo tengo una recompensa, he decidido recompensar a ya que su código se mejor a mis necesidades (no lo he escrito en mi pregunta, pero la idea de escribir un servicio tan simple, como he presentado en mi pregunta, es ocultar) a partir de los detalles de la implementación del usuario final y no utilice JsonArray y similares en la respuesta de ).

Actualización 1:

El único problema con la respuesta de es que, sugirió que el modelo Size no necesita ninguna anotación, lo que es totalmente incorrecto para el ejemplo de JSON citado.

Para el caso anterior, dos campos exactos del modelo de Size necesitan anotaciones : created_at y updated_at .

Incluso he probado algunas versiones de la biblioteca converter-gson (vi que se usaba además de mí), no ha cambiado nada. Las anotaciones eran necesarias.

De lo contrario - de nuevo, muchas gracias!

He creado un punto final REST simple:

http://<server_address>:3000/sizes

Esta URL devuelve una respuesta muy simple que contiene una matriz json de la siguiente manera:

[ { "id": 1, "name": "Small", "active": true }, { "id": 2, "name": "Medium", "active": true }, { "id": 3, "name": "Large", "active": true } ]

Ahora, estoy tratando de consumir esta respuesta usando Retrofit 2 con GSON .

He añadido un modelo:

@lombok.AllArgsConstructor @lombok.EqualsAndHashCode @lombok.ToString public class Size { private int id; private String name; private boolean active; @SerializedName("created_at") private String createdAt; @SerializedName("updated_at") private String updatedAt; }

Y servicio:

public interface Service { @GET("sizes") Call<List<Size>> loadSizes(); }

He instanciado un Retrofit:

Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://<server_address>:3000") .addConverterFactory(GsonConverterFactory.create()) .build();

Y mi servicio:

Service service = retrofit.create(Service.class);

Ahora, tratando de llamar a los datos:

service.loadSizes().enqueue(new Callback<List<Size>>() { @Override public void onResponse(Call<List<Size>> call, Response<List<Size>> response) { for(Size size: response.body()) { System.out.println(size.toString()); } } @Override public void onFailure(Call<List<Size>> call, Throwable t) { System.out.println(t.getMessage()); } });

Lo que termina con una excepción:

java.lang.IllegalStateException : se esperaba BEGIN_OBJECT pero fue STRING en la línea 1 columna 18 ruta $ [0] .name

Supongo que el error se debe a eso, la API REST devuelve una respuesta que es una matriz o un objeto .

  1. ¿Estoy en lo correcto?
  2. ¿Cuál es la forma más fácil de hacer que este código funcione?

El servicio REST no se puede modificar , por lo que la respuesta debe permanecer como está.

Además, la deserialización del json anterior utilizando GSON puro se puede realizar mediante:

Type sizesType = new TypeToken<List<Size>>(){}.getType(); List<Size> size = new Gson().fromJson(json, sizesType);

Pero no tengo idea de cómo hacer Retrofit 2 para usar esto.

Gracias por adelantado.


Por favor use lo siguiente:

archivo build.gradle:

dependencies { ... compile ''com.squareup.retrofit2:retrofit:2.0.1'' compile ''com.squareup.retrofit2:converter-gson:2.0.1'' compile ''com.google.code.gson:gson:2.6.2'' }

WebAPIService.java:

public interface WebAPIService { @GET("/json.txt") // I use a simple json file to get the JSON Array as yours Call<JsonArray> readJsonArray(); }

Tamaño.java:

public class Size { @SerializedName("id") private int id; @SerializedName("name") private String name; @SerializedName("active") private boolean active; @SerializedName("created_At") private String createdAt; @SerializedName("updated_at") private String updatedAt; }

MainActivity.java:

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://...") .addConverterFactory(GsonConverterFactory.create()) .build(); WebAPIService service = retrofit.create(WebAPIService.class); Call<JsonArray> jsonCall = service.readJsonArray(); jsonCall.enqueue(new Callback<JsonArray>() { @Override public void onResponse(Call<JsonArray> call, Response<JsonArray> response) { String jsonString = response.body().toString(); Log.i("onResponse", jsonString); Type listType = new TypeToken<List<Size>>() {}.getType(); List<Size> yourList = new Gson().fromJson(jsonString, listType); Log.i("onResponse", yourList.toString()); } @Override public void onFailure(Call<JsonArray> call, Throwable t) { Log.e("onFailure", t.toString()); } }); }

Aquí está la captura de pantalla de depuración:

ACTUALIZACIÓN: También puede utilizar la siguiente opción:

@GET("/json.txt") Call<List<Size>> readList();

y

Call<List<Size>> listCall1 = service.readList(); listCall1.enqueue(new Callback<List<Size>>() { @Override public void onResponse(Call<List<Size>> call, Response<List<Size>> response) { for (Size size : response.body()){ Log.i("onResponse", size.toString()); } } @Override public void onFailure(Call<List<Size>> call, Throwable t) { Log.e("onFailure", t.toString()); } });


Recientemente acabo de terminar un proyecto relacionado con retrofit2. Basándome en mi fuente, copio todas tus cosas en mi proyecto para intentarlo, haciendo algunos cambios menores, funciona bien de mi lado.

En tu build.gradle, agrega esos:

compile ''com.squareup.retrofit2:retrofit:2.0.1'' compile ''com.google.code.gson:gson:2.6.2'' compile ''com.squareup.okhttp3:okhttp:3.1.2'' compile ''com.squareup.retrofit2:converter-gson:2.0.1'' compile ''com.squareup.okhttp3:logging-interceptor:3.2.0''

Modelo: ( ACTUALIZACIÓN: siga el caso de tommus, createdAt y updatedAt ahora se muestra en su ejemplo de respuesta json, estos dos valores necesitan anotación debido a que el nombre en el modelo es diferente de json respone )

public class Size { private int id; private String name; private boolean active; @SerializedName("created_at") private String createdAt; @SerializedName("updated_at") private String updatedAt; }

Servicio: (Exactamente lo mismo que tienes)

public interface service { @GET("sizes") Call<List<Size>> loadSizes(); }

RestClient: ( agrego el registro aquí, para que pueda ver toda la información de la solicitud y la respuesta, tenga cuidado de no usar Localhost sino la dirección IP de su servidor en la URL )

import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.xiaoyaoworm.prolificlibrary.test.Service; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class RestClient { private static Service service; public static Service getClient() { if (service == null) { Gson gson = new GsonBuilder() .setDateFormat("yyyy-MM-dd''T''HH:mm:ssZ") .create(); // Add logging into retrofit 2.0 HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); httpClient.interceptors().add(logging); Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://YOURSERVERIPNOTLOCALHOST:3000/") .addConverterFactory(GsonConverterFactory.create(gson)) .client(httpClient.build()).build(); service = retrofit.create(Service.class); } return service; } }

En su actividad, agregue esta función para ejecutar su código: ( exactamente igual a lo que ha hecho. La respuesta será su lista de tamaños )

private void loadSize() { Service serviceAPI = RestClient.getClient(); Call<List<Size>> loadSizeCall = serviceAPI.loadSizes(); loadSizeCall.enqueue(new Callback<List<Size>>() { @Override public void onResponse(Call<List<Size>> call, Response<List<Size>> response) { for(Size size: response.body()) { System.out.println(size.toString()); } } @Override public void onFailure(Call<List<Size>> call, Throwable t) { System.out.println(t.getMessage()); } }); }

Ejecutando esto verá la información que desea imprimir:

Aquí está mi repositorio github que uso retrofit2.0 para hacer que el trabajo simple GET POST PUT DELETE funcione. Puedes usar esto como referencia. Mi Github retrofit2.0 repo