MalformedJsonException con API de Retrofit?

Necesito enviar un json a mi webservice, json es:

{ "Sala": { "usuario": "%@", "adversario": "%@", "atualizacao": "%@", "device": "%@", "device_tipo": "ios" } } 

. Estoy tratando de hacerlo utilizando Retrofit API 1.8. Cuando intento enviar el poste lanza una excepción.

Excepción:

 com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 7 path $ 

Estoy intentando esto

 public class ChatObject { private String usuario; private String adversario; private String atualizacao; private String email; private String device; private String device_tipo; 

Interfaz de Retrofit

 @POST("/WsChat/interacao.json") public void onReceiveMessage(@Body ChatObject obj, Callback<JsonElement> response); 

Implementos

 public void receiveMessage(){ ///{\"Sala\":{\"usuario\":\"%@\",\"adversario\":\"%@\",\"atualizacao\":\"%@\",\"device\":\"%@\",\"device_tipo\":\"ios\"}} ChatObject chatObject = new ChatObject(BatalhaConfigs.USUARIO_EMAIL, BatalhaConfigs.ADVERSARIO_EMAIL, new Date().toString(), BatalhaConfigs.USUARIO_EMAIL, AndroidReturnId.getAndroidId(), "android"); RestAdapter adapter = new RestAdapter.Builder() .setLogLevel(RestAdapter.LogLevel.FULL) .setRequestInterceptor(new CustomRequestInterceptor()) .setEndpoint(END_POINT) .build(); ChatListener listener = adapter.create(ChatListener.class); listener.onReceiveMessage(chatObject, new Callback<JsonElement>() { @Override public void success(JsonElement jsonElement, retrofit.client.Response response) { Log.i("JSON ELEMENT->", jsonElement.toString()); } @Override public void failure(RetrofitError error) { Log.i("FALHOU->", error.getLocalizedMessage()); } }); } 

com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) se suele lanzar cuando hay algunos caracteres que malforman el JSON. El propio mensaje de excepción sugiere que la deserialización sea más tolerante.

Pero le sugiero que arreglar su JSON y recortarlo de caracteres no deseados.

Debe extender GsonConverter y anular fromBody() para que Gson lea desde el JsonReader tolerante. A continuación, sólo tiene que establecerlo en su RestAdapter . Esto intentará usar JsonReader tolerante para deserializar y luego cerrarlo, si no se produce una excepción.

 public class LenientGsonConverter extends GsonConverter { private Gson mGson; public LenientGsonConverter(Gson gson) { super(gson); mGson = gson; } public LenientGsonConverter(Gson gson, String charset) { super(gson, charset); mGson = gson; } @Override public Object fromBody(TypedInput body, Type type) throws ConversionException { boolean willCloseStream = false; // try to close the stream, if there is no exception thrown using tolerant JsonReader try { JsonReader jsonReader = new JsonReader(new InputStreamReader(body.in())); jsonReader.setLenient(true); Object o = mGson.fromJson(jsonReader,type); willCloseStream = true; return o; } catch (IOException e) { e.printStackTrace(); }finally { if(willCloseStream) { closeStream(body); } } return super.fromBody(body, type); } private void closeStream(TypedInput body){ try { InputStream in = body.in(); in.close(); } catch (IOException e) { e.printStackTrace(); } } } 

}

Parece que ha cambiado ligeramente con Retrofit 2.0

He aquí cómo lo hice:

  Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://whatever.com") .addConverterFactory(LenientGsonConverterFactory.create(gson)) .build(); 

Una nueva fábrica leniente de gson:

 public final class LenientGsonConverterFactory extends Converter.Factory { /** * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and * decoding from JSON (when no charset is specified by a header) will use UTF-8. */ public static LenientGsonConverterFactory create() { return create(new Gson()); } /** * Create an instance using {@code gson} for conversion. Encoding to JSON and * decoding from JSON (when no charset is specified by a header) will use UTF-8. */ public static LenientGsonConverterFactory create(Gson gson) { return new LenientGsonConverterFactory(gson); } private final Gson gson; private LenientGsonConverterFactory(Gson gson) { if (gson == null) throw new NullPointerException("gson == null"); this.gson = gson; } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new LenientGsonResponseBodyConverter<>(gson, adapter); } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new LenientGsonRequestBodyConverter<>(gson, adapter); } } 

Análisis sin sentido de las respuestas:

  private class LenientGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> { private final Gson gson; private final TypeAdapter<T> adapter; LenientGsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); jsonReader.setLenient(true); try { return adapter.read(jsonReader); } finally { value.close(); } } } 

Leniente creación de solicitudes:

  private class LenientGsonRequestBodyConverter<T> implements Converter<T, RequestBody> { private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8"); private static final Charset UTF_8 = Charset.forName("UTF-8"); private final Gson gson; private final TypeAdapter<T> adapter; LenientGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public RequestBody convert(T value) throws IOException { Buffer buffer = new Buffer(); Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8); JsonWriter jsonWriter = gson.newJsonWriter(writer); jsonWriter.setLenient(true); adapter.write(jsonWriter, value); jsonWriter.close(); return RequestBody.create(MEDIA_TYPE, buffer.readByteString()); } } 

Acabo de copiar el código fuente Retrofit y agregó una línea a la solicitud y los convertidores de respuesta jsonWriter.setLenient(true);


O incluso más fácil:

  Gson gson = new GsonBuilder() .setLenient() .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://whatever.com") .addConverterFactory(GsonConverterFactory.create(gson)) .build(); 
  RestAdapter adapterRfqPost = new RestAdapter.Builder() .setEndpoint(Constants.ENDPOINT) `enter code here`.setConverter(new ConstantsMethods.StringConverter()) .build(); 

 public static class StringConverter implements Converter { @Override public Object fromBody(TypedInput typedInput, Type type) throws ConversionException { String text = null; try { text = fromStream(typedInput.in()); } catch (IOException ignored) {/*NOP*/ } return text; } @Override public TypedOutput toBody(Object o) { return null; } public static String fromStream(InputStream in) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder out = new StringBuilder(); String newLine = System.getProperty("line.separator"); String line; while ((line = reader.readLine()) != null) { out.append(line); out.append(newLine); } return out.toString(); } } 

Debe ayudar a este código:

 RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("http://192.168.10.115/test.php") .setConverter(new GsonConverter(new Gson())) .build(); 

Ponga el archivo jar:

 [gson-2.2.2.jar][1] 
  • Rx java retrofit 2 manejo de errores
  • Error de petición Uber
  • ¿Tenemos alguna posibilidad de detener la solicitud en OkHttp Interceptor?
  • RxJava se vuelve a suscribir al evento tras la restauración de la actividad
  • Problemas con los últimos frascos de Square - retrofit, okhttp, okio y okhttp-urlconnection
  • Solicitudes HTTP periódicas con RxJava y Retrofit
  • Consulta GET con json - Retrofit 2.0
  • ¿Cómo puedo hacer peticiones simultáneas más rápido con Retrofit / OkHttp?
  • ¿Cómo manejar parámetros que pueden ser ARRAY u OBJECT en Retrofit en Android?
  • Ajustar la variable json del mapa a la palabra clave
  • Retrofit: Se esperaba BEGIN_OBJECT pero era BEGIN_ARRAY
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.