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();