¿MalformedJsonException con Retrofit API?

Necesito enviar un json a mi servicio web, json es:

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

. Estoy intentando hacerlo usando Retrofit API 1.8. Cuando bash enviar la publicación arroja 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 reequipamiento

 @POST("/WsChat/interacao.json") public void onReceiveMessage(@Body ChatObject obj, Callback 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() { @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) generalmente se lanza cuando hay algunos caracteres que deforman el JSON. El mensaje de excepción en sí mismo sugiere que la deserialización sea más tolerante.

Pero te sugiero que arregles tu JSON y lo recortes de los caracteres no deseados.

Debería extender GsonConverter y anular fromBody() para hacer que Gson lea del JsonReader tolerante. Luego simplemente RestAdapter tu RestAdapter . Esto intentará usar JsonReader tolerante para deserializar y luego cerrarlo, si no se lanza 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

Así es como lo hice:

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

Una nueva fábrica gson indulgente:

 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 responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter adapter = gson.getAdapter(TypeToken.get(type)); return new LenientGsonResponseBodyConverter<>(gson, adapter); } @Override public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { TypeAdapter adapter = gson.getAdapter(TypeToken.get(type)); return new LenientGsonRequestBodyConverter<>(gson, adapter); } } 

Lento análisis de respuestas:

  private class LenientGsonResponseBodyConverter implements Converter { private final Gson gson; private final TypeAdapter adapter; LenientGsonResponseBodyConverter(Gson gson, TypeAdapter 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(); } } } 

Lentitud en la creación de solicitudes:

  private class LenientGsonRequestBodyConverter implements Converter { 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 adapter; LenientGsonRequestBodyConverter(Gson gson, TypeAdapter 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 de Retrofit y agregué una línea a la solicitud y a 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(); } } 

Deberías ayudar a este código:

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

Poner archivo jar:

 [gson-2.2.2.jar][1]