recyclerview library implementar example android rest http-post retrofit android-json

android - library - retrofit post json



¿Cómo POSTAR JSON entero sin procesar en el cuerpo de una solicitud de modificación? (11)

1) Añadir dependencias-

compile ''com.google.code.gson:gson:2.6.2'' compile ''com.squareup.retrofit2:retrofit:2.3.0'' compile ''com.squareup.retrofit2:converter-gson:2.3.0''

2) hacer clase de manipulador de api

public class ApiHandler { public static final String BASE_URL = "URL"; private static Webservices apiService; public static Webservices getApiService() { if (apiService == null) { Gson gson = new GsonBuilder() .setLenient() .create(); Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(BASE_URL).build(); apiService = retrofit.create(Webservices.class); return apiService; } else { return apiService; } } }

3) hacer clases de frijol de Json schema 2 pojo

Recuerda
- Idioma de destino: Java - Tipo de origen: JSON - Estilo de anotación: Gson - seleccione Incluir captadores y definidores - también puede seleccionar Permitir propiedades adicionales

http://www.jsonschema2pojo.org/

4) hacer interfaz para llamadas api

public interface Webservices { @POST("ApiUrlpath") Call<ResponseBean> ApiName(@Body JsonObject jsonBody); }

Si tiene parámetros de datos de formulario, agregue debajo de la línea

@Headers("Content-Type: application/x-www-form-urlencoded")

Otra forma para el parámetro de datos de formulario ver este link

5) hacer JsonObject para pasar al cuerpo como parámetro

private JsonObject ApiJsonMap() { JsonObject gsonObject = new JsonObject(); try { JSONObject jsonObj_ = new JSONObject(); jsonObj_.put("key", "value"); jsonObj_.put("key", "value"); jsonObj_.put("key", "value"); JsonParser jsonParser = new JsonParser(); gsonObject = (JsonObject) jsonParser.parse(jsonObj_.toString()); //print parameter Log.e("MY gson.JSON: ", "AS PARAMETER " + gsonObject); } catch (JSONException e) { e.printStackTrace(); } return gsonObject; }

6) Llama a Api como este

private void ApiCallMethod() { try { if (CommonUtils.isConnectingToInternet(MyActivity.this)) { final ProgressDialog dialog; dialog = new ProgressDialog(MyActivity.this); dialog.setMessage("Loading..."); dialog.setCanceledOnTouchOutside(false); dialog.show(); Call<ResponseBean> registerCall = ApiHandler.getApiService().ApiName(ApiJsonMap()); registerCall.enqueue(new retrofit2.Callback<ResponseBean>() { @Override public void onResponse(Call<ResponseBean> registerCall, retrofit2.Response<ResponseBean> response) { try { //print respone Log.e(" Full json gson => ", new Gson().toJson(response)); JSONObject jsonObj = new JSONObject(new Gson().toJson(response).toString()); Log.e(" responce => ", jsonObj.getJSONObject("body").toString()); if (response.isSuccessful()) { dialog.dismiss(); int success = response.body().getSuccess(); if (success == 1) { } else if (success == 0) { } } else { dialog.dismiss(); } } catch (Exception e) { e.printStackTrace(); try { Log.e("Tag", "error=" + e.toString()); dialog.dismiss(); } catch (Resources.NotFoundException e1) { e1.printStackTrace(); } } } @Override public void onFailure(Call<ResponseBean> call, Throwable t) { try { Log.e("Tag", "error" + t.toString()); dialog.dismiss(); } catch (Resources.NotFoundException e) { e.printStackTrace(); } } }); } else { Log.e("Tag", "error= Alert no internet"); } } catch (Resources.NotFoundException e) { e.printStackTrace(); } }

Esta pregunta puede haber sido hecha antes, pero no fue contestada definitivamente. ¿Cómo exactamente se publica JSON entero sin procesar dentro del cuerpo de una solicitud de modificación?

Ver pregunta similar here . ¿O es correcta esta respuesta que debe estar codificada en url de forma y pasada como un campo ? Realmente espero que no, ya que los servicios a los que me estoy conectando solo esperan JSON en bruto en el cuerpo de la publicación. No están configurados para buscar un campo particular para los datos JSON.

Solo quiero aclarar esto con los demás de una vez por todas. Una persona respondió a no usar Retrofit. El otro no estaba seguro de la sintaxis. Otro piensa que sí se puede hacer, pero solo si su forma está codificada con url y colocada en un campo (eso no es aceptable en mi caso). No, no puedo volver a codificar todos los servicios para mi cliente Android. Y sí, es muy común en los grandes proyectos publicar JSON sin formato en lugar de pasar el contenido de JSON como valores de propiedades de campo. Vamos a hacerlo bien y seguir adelante. ¿Alguien puede señalar la documentación o el ejemplo que muestra cómo se hace esto? O proporcionar una razón válida por la que no se puede o no debe hacerse.

ACTUALIZACIÓN: Una cosa puedo decir con 100% de certeza. Puedes hacer esto en Volley de Google. Está integrado. ¿Podemos hacer esto en Retrofit?


Después de tanto esfuerzo, descubrí que la diferencia básica es que necesitas enviar JsonObject lugar de JSONObject como parámetro.


En Retrofit2 , cuando desee enviar sus parámetros en bruto, debe usar Scalars .

Primero agrega esto en tu gradle:

compile ''com.squareup.retrofit2:retrofit:2.3.0'' compile ''com.squareup.retrofit2:converter-gson:2.3.0'' compile ''com.squareup.retrofit2:converter-scalars:2.3.0''

Su interfaz

public interface ApiInterface { String URL_BASE = "http://10.157.102.22/rest/"; @Headers("Content-Type: application/json") @POST("login") Call<User> getUser(@Body String body); }

Actividad

public class SampleActivity extends AppCompatActivity implements Callback<User> { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sample); Retrofit retrofit = new Retrofit.Builder() .baseUrl(ApiInterface.URL_BASE) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); ApiInterface apiInterface = retrofit.create(ApiInterface.class); // prepare call in Retrofit 2.0 try { JSONObject paramObject = new JSONObject(); paramObject.put("email", "[email protected]"); paramObject.put("pass", "4384984938943"); Call<User> userCall = apiInterface.getUser(paramObject.toString()); userCall.enqueue(this); } catch (JSONException e) { e.printStackTrace(); } } @Override public void onResponse(Call<User> call, Response<User> response) { } @Override public void onFailure(Call<User> call, Throwable t) { } }


En lugar de clases, también podemos usar directamente el HashMap<String, Object> para enviar parámetros del cuerpo, por ejemplo.

interface Foo { @POST("/jayson") FooResponse postJson(@Body HashMap<String, Object> body); }


Intenté esto: cuando está creando su instancia de actualización, agregue esta fábrica de convertidores al generador de modificaciones:

gsonBuilder = new GsonBuilder().serializeNulls() your_retrofit_instance = Retrofit.Builder().addConverterFactory( GsonConverterFactory.create( gsonBuilder.create() ) )


Me gusta especialmente la sugerencia de Jake de la subclase TypedString above . De hecho, podría crear una variedad de subclases basadas en el tipo de datos POST que planea subir, cada uno con su propio conjunto personalizado de ajustes consistentes.

También tiene la opción de agregar una anotación de encabezado a sus métodos JSON POST en su API de actualización ...

@Headers( "Content-Type: application/json" ) @POST("/json/foo/bar/") Response fubar( @Body TypedString sJsonBody ) ;

... pero el uso de una subclase es más autodocumentado.

@POST("/json/foo/bar") Response fubar( @Body TypedJsonString jsonBody ) ;


Sí, ya sé que es tarde, pero alguien probablemente se beneficiaría de esto.

Utilizando Retrofit2:

Encontré este problema anoche, migrando de Volley a Retrofit2 (y como dice OP, esto se JsonObjectRequest en Volley con JsonObjectRequest ), y aunque la respuesta de Jake es la correcta para Retrofit1.9 , Retrofit2 no tiene TypedString .

Mi caso requirió el envío de un Map<String,Object> que podría contener algunos valores nulos, convertido a JSONObject (que no volará con @FieldMap , ni tampoco caracteres especiales, algunos se convierten), por lo que siguiendo la sugerencia de @bnorms, y como declarado por la Square :

Se puede especificar un objeto para su uso como un cuerpo de solicitud HTTP con la anotación @Body.

El objeto también se convertirá utilizando un convertidor especificado en la instancia de Retrofit. Si no se agrega ningún convertidor, solo se puede usar RequestBody.

Así que esta es una opción que usa RequestBody y ResponseBody :

En tu interfaz usa @Body con RequestBody

public interface ServiceApi { @POST("prefix/user/{login}") Call<ResponseBody> login(@Path("login") String postfix, @Body RequestBody params); }

En su punto de llamada, cree un RequestBody , indicando que es MediaType y usando JSONObject para convertir su Mapa al formato adecuado:

Map<String, Object> jsonParams = new ArrayMap<>(); //put something inside the map, could be null jsonParams.put("code", some_code); RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),(new JSONObject(jsonParams)).toString()); //serviceCaller is the interface initialized with retrofit.create... Call<ResponseBody> response = serviceCaller.login("loginpostfix", body); response.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse) { try { //get your response.... Log.d(TAG, "RetroFit2.0 :RetroGetLogin: " + rawResponse.body().string()); } catch (Exception e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable throwable) { // other stuff... } });

Espero que esto ayude a cualquiera!

Una versión elegante de Kotlin de lo anterior, para permitir abstraer los parámetros de la conversión JSON en el resto del código de su aplicación:

interface ServiceApi { fun login(username: String, password: String) = jsonLogin(createJsonRequestBody( "username" to username, "password" to password)) @POST("/api/login") fun jsonLogin(@Body params: RequestBody): Deferred<LoginResult> private fun createJsonRequestBody(vararg params: Pair<String, String>) = RequestBody.create( okhttp3.MediaType.parse("application/json; charset=utf-8"), JSONObject(mapOf(*params)).toString()) }


Según la respuesta principal, tengo una solución para no tener que hacer POJO para cada solicitud.

Ejemplo, quiero publicar este JSON.

{ "data" : { "mobile" : "qwer", "password" : "qwer" }, "commom" : {} }

Entonces, creo una clase común como esta:

import java.util.Map; import java.util.HashMap; public class WRequest { Map<String, Object> data; Map<String, Object> common; public WRequest() { data = new HashMap<>(); common = new HashMap<>(); } }

Finalmente, cuando necesito un json.

WRequest request = new WRequest(); request.data.put("type", type); request.data.put("page", page);

La solicitud marcada con la anotación @Body puede pasar a Retrofit.


Usar JsonObject es como es:

  1. Crea tu interfaz así:

    public interface laInterfaz{ @POST("/bleh/blah/org") void registerPayer(@Body JsonObject bean, Callback<JsonObject> callback); }

  2. Hacer el JsonObject de acuerdo con la estructura jsons.

    JsonObject obj = new JsonObject(); JsonObject payerReg = new JsonObject(); payerReg.addProperty("crc","aas22"); payerReg.addProperty("payerDevManufacturer","Samsung"); obj.add("payerReg",payerReg); /*json/* {"payerReg":{"crc":"aas22","payerDevManufacturer":"Samsung"}} /*json*/

  3. Llame al servicio:

    service.registerPayer(obj, callBackRegistraPagador); Callback<JsonObject> callBackRegistraPagador = new Callback<JsonObject>(){ public void success(JsonObject object, Response response){ System.out.println(object.toString()); } public void failure(RetrofitError retrofitError){ System.out.println(retrofitError.toString()); }

    };

Y eso es! En mi opinión personal, es mucho mejor que hacer pojos y trabajar con el desorden de la clase. Esto es mucho más limpio.


usar lo siguiente para enviar json

final JSONObject jsonBody = new JSONObject(); try { jsonBody.put("key", "value"); } catch (JSONException e){ e.printStackTrace(); } RequestBody body = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),(jsonBody).toString());

y pasarlo a url

@Body RequestBody key


La anotación @Body define un solo cuerpo de solicitud.

interface Foo { @POST("/jayson") FooResponse postJson(@Body FooRequest body); }

Como Retrofit usa Gson de forma predeterminada, las instancias de FooRequest se serializarán como JSON como el único cuerpo de la solicitud.

public class FooRequest { final String foo; final String bar; FooRequest(String foo, String bar) { this.foo = foo; this.bar = bar; } }

Llamando con:

FooResponse = foo.postJson(new FooRequest("kit", "kat"));

Dará el siguiente cuerpo:

{"foo":"kit","bar":"kat"}

Los documentos de Gson tienen mucho más sobre cómo funciona la serialización de objetos.

Ahora, si realmente quieres enviar JSON "sin procesar" como el cuerpo tú mismo (¡pero por favor usa Gson para esto!) Todavía puedes usar TypedInput :

interface Foo { @POST("/jayson") FooResponse postRawJson(@Body TypedInput body); }

TypedInput se define como "Datos binarios con un tipo mime asociado". Hay dos formas de enviar fácilmente datos sin procesar con la declaración anterior:

  1. Utilice TypedByteArray para enviar bytes sin procesar y el tipo mime JSON:

    String json = "{/"foo/":/"kit/",/"bar/":/"kat/"}"; TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8")); FooResponse response = foo.postRawJson(in);

  2. Subclase TypedString para crear una clase TypedJsonString :

    public class TypedJsonString extends TypedString { public TypedJsonString(String body) { super(body); } @Override public String mimeType() { return "application/json"; } }

    Y luego use una instancia de esa clase similar a # 1.