2014-12-15 11 views
14

Ho bisogno di inviare un JSON al mio webservice, JSON è:MalformedJsonException with Retrofit API?

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

. Sto provando a farlo usando Retrofit API 1.8. Quando provo a inviare il post genera un'eccezione.

Eccezione:

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

sto cercando questo

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

Retrofit interfaccia

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

Utensili

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

     } 
    }); 
} 
+0

non è l'output JSON per 'ChatObject' sta per essere {{usuario ":"% @ "," adversario ":"% @ "," atualizacao ":"% @ "," email ":"% @ "," dispositivo ":"% @ ", "device_tipo": "% @"} ' –

risposta

14

com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) è di solito gettati quando c'è qualche personaggio (s) che malforms il JSON. Il messaggio di eccezione suggerisce di rendere la deserializzazione più tollerante.

Ma ti suggerisco di sistemare il tuo JSON e tagliarlo da caratteri indesiderati.

È necessario estendere GsonConverter e ignorare fromBody() per rendere letto dalla tolleranza JsonReader. Quindi basta impostarlo sul tuo RestAdapter. Questo tenterà di usare il tollerante JsonReader per deserializzare e quindi chiuderlo, se non viene lanciata un'eccezione.

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

}

+1

Nikola ,,, Come chiamare questa funzione significa ,,,, .setConverter (new LenientGsonConverter (gson)) –

+0

Si chiama questo quando crei il tuo' RestAdapter'. –

+1

GSON GSON = new GsonBuilder() \t \t \t \t .setFieldNamingPolicy (FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) \t \t \t \t .registerTypeAdapter (Date.class, nuovo DateTypeAdapter()) \t \t \t \t .create(); \t \t \t \t \t \t \t \t \t \t \t \t RestAdapter restAdapter = new RestAdapter.Builder() \t \t \t \t .setEndpoint (urlString) \t \t \t \t .setConverter (nuovo LenientGsonConverter (GSON)) \t \t \t \t .build(); Questo non funziona –

-11

Si dovrebbe contribuire a questo codice:

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

Put file jar:

[gson-2.2.2.jar][1] 
+0

Ciò non rende GSON lient. –

1
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(); 
     } 
    } 
+0

Puoi aggiungere qualche spiegazione a questa risposta? In che modo questo codice risolve il problema? Cosa sta cambiando? –

8

Sembra leggermente modificato con Retrofit 2.0

Ecco come ho fatto:

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

Un nuovo stabilimento 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<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); 
     } 

    } 

Lenient analisi di risposte:

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

creazione Lenient di richieste:

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

Io ho semplicemente copiato il codice sorgente Retrofit e ha aggiunto una linea per la richiesta e convertitori di risposta jsonWriter.setLenient(true);


O ancora più semplice:

Gson gson = new GsonBuilder() 
     .setLenient() 
     .create(); 

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

ho questo errore non può risolvere setLenient(), in 'com.squareup.retrofit2: convertitore-gson: 2.0.0-beta4' –

+0

@ZachariaMwalwama l'ultima versione è '2.0.2' http://search.maven.org/# search% 7Cga% 7C1% 7Cconverter-gson – Blundell

+0

thhhaaaaanks sir –