volley httplogginginterceptor español httpclient retrofit okhttp androidhttpclient

httpclient - httplogginginterceptor - Retrofit 2.0-beta-2 está agregando citas literales a los valores de varias partes



httplogginginterceptor retrofit2 (7)

¿Qué hay que hacer de esa manera?

RequestBody caption = RequestBody.create(MediaType.parse("text/plain"), new String("caption"));

Fui a actualizar a Retrofit 2.0 y me encontré con este extraño problema.

Tengo un método para iniciar sesión en un usuario

public interface ApiInterface { @Multipart @POST("user/login/") Call<SessionToken> userLogin(@Part("username") String username, @Part("password") String password); }

Cuando miro el valor clave POST params en el lado del servidor, se imprimen así

username : "brian" password : "password"

El mismo método que usa la modificación 1.9, los pares K: V parecen

username : brian password : password

Es agregar citas literales a las variables POST

Si utilizo cualquier otro cliente de descanso, las variables se imprimen como la segunda forma sin las comillas.

Así es como construyo la instancia de Retrofit con un interceptor

OkHttpClient client = new OkHttpClient(); client.interceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); // Customize the request Request request = original.newBuilder() .header("Accept", "application/json") .header("Authorization", myPrefs.accessToken().getOr("")) .method(original.method(), original.body()) .build(); Response response = chain.proceed(request); // Customize or return the response return response; } }); Ok2Curl.set(client); Retrofit retrofit = new Retrofit.Builder() .baseUrl(apiEndpoint) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build();

Me imagino que estoy haciendo algo mal con el convertidor pero no estoy seguro de qué.

¿Alguien más se ha encontrado con este problema todavía? Sé que está en beta, pero se usa bastante ampliamente.


Aquí es cómo resolverlo,

En primer lugar:

return new Retrofit.Builder() .baseUrl(Env.GetApiBaseUrl()) .addConverterFactory(new GsonStringConverterFactory()) .addConverterFactory(GsonConverterFactory.create(gson)) .client(getHttpClient()) .build();

Cree un CustomConverter como este, esto es necesario para Retrofit 2, a menos que algunas corrijan la "característica" agregada en v2.

public class GsonStringConverterFactory extends Converter.Factory { private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain"); @Override public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) { if (String.class.equals(type))// || (type instanceof Class && ((Class<?>) type).isEnum())) { return new Converter<String, RequestBody>() { @Override public RequestBody convert(String value) throws IOException { return RequestBody.create(MEDIA_TYPE, value); } }; } return null; } }


Esto se debe a que se está ejecutando a través del convertidor JSON.

Solución 1: use RequestBody lugar de String

public interface ApiInterface { @Multipart @POST("user/login/") Call<SessionToken> userLogin(@Part("username") RequestBody username, @Part("password") RequestBody password); }

Build RequestBody:

RequestBody usernameBody = RequestBody.create(MediaType.parse("text/plain"), usernameStr); RequestBody passwordBody = RequestBody.create(MediaType.parse("text/plain"), passwordStr);

Iniciar la operación de red:

retrofit.create(ApiInterface.class).userLogin(usernameBody , passwordBody).enqueue()....

Solución 2: cree un ConverterFactory personalizado para eliminar el valor de la parte de la cadena.

Para: Retrofit2 versión final no beta. (com.squareup.retrofit2: actualización: 2.0.0)

Crea tu StringConverterFactory:

public class StringConverterFactory extends Converter.Factory { private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain"); public static StringConverterFactory create() { return new StringConverterFactory(); } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { if (String.class.equals(type)) { return new Converter<ResponseBody, String>() { @Override public String convert(ResponseBody value) throws IOException { return value.string(); } }; } return null; } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { if(String.class.equals(type)) { return new Converter<String, RequestBody>() { @Override public RequestBody convert(String value) throws IOException { return RequestBody.create(MEDIA_TYPE, value); } }; } return null; } }

Agregue a su instancia de actualización:

retrofit = new Retrofit.Builder() .baseUrl(SERVER_URL) .client(client) .addConverterFactory(StringConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();

Atención: ¡ StringConverterFactory debe agregarse antes de GsonConverterFactory !

entonces puedes usar String como parte del valor directamente.

Puede encontrar más información sobre este problema en https://github.com/square/retrofit/issues/1210


He encontrado otra solución, excepto those . Trabajó con Retrofit 2.1.0. (El adaptador Rx es opcional aquí)

Mi interfaz de actualización se ve así:

@POST("/children/add") Observable<Child> addChild(@Body RequestBody requestBody);

Y en ApiManager lo uso así:

@Override public Observable<Child> addChild(String firstName, String lastName, Long birthDate, @Nullable File passportPicture) { MultipartBody.Builder builder = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("first_name", firstName) .addFormDataPart("last_name", lastName) .addFormDataPart("birth_date", birthDate + ""); //some nullable optional parameter if (passportPicture != null) { builder.addFormDataPart("certificate", passportPicture.getName(), RequestBody.create(MediaType.parse("image/*"), passportPicture)); } return api.addChild(builder.build()); }

Es similar a la Solución 1 de Loyea, pero creo que es un poco más elegante.


No sé si es demasiado tarde, pero también podemos enviar solicitudes con RequestBody.

Ejemplo:

public interface ApiInterface { @Multipart @POST("user/login/") Call<SessionToken> userLogin(@Part("username") String username, @Part("password") String password); }

Podemos convertir de la siguiente manera:

public interface ApiInterface { @Multipart @POST("user/login/") Call<SessionToken> userLogin(@Part("username") RequestBody username, @Part("password") String password); }


Si su interfaz de usuario muestra sus respuestas con comillas, puede usar getAsString lugar de toString


Tengo el mismo problema, y ​​como se resolvió:

1) Añadir a build.gradle:

compile ''com.squareup.retrofit2:converter-scalars:2.1.0'' // Remember to add the same version

2) Agregue una línea aquí:

Retrofit retrofit = new Retrofit.Builder() .baseUrl(URL_BASE) .addConverterFactory(ScalarsConverterFactory.create()) // this line .addConverterFactory(GsonConverterFactory.create(gson)) .client(getUnsafeOkHttpClient()) .build();