2015-02-13 17 views
5

Immaginate la seguente richiesta:Serialize Query-Parameter in Retrofit

@POST("/recipes/create") 
void createRecipe(@Query("recipe") Recipe recipe, Callback<String> callback); 

Mi piacerebbe avere toJSON (ricetta) ma toString purtroppo la mia richiesta è solo chiamando() per la mia ricetta che non funziona affatto.

Potrei sovrascrivere il toString all'interno della ricetta ma preferirei avere una soluzione generale.

non posso usare @Body come ho bisogno di specificare, quello che sto inviando (ho bisogno di avere "ricetta = json (theRecipe)".

anche io non può cambiare la serializzazione di aggiungere "ricetta =" come io non sono responsabile del server.

al momento sto usando un QueryMap Mappa dove ho messo in un oggetto serializzato. Anche se questo funziona, non è una soluzione molto elegante a mio parere.

Posso intercettare in qualche modo l'adattatore di retrofit?

risposta

6

Non credo che supporti questo in questo momento in un modo carino. Controllare questa risposta da uno degli autori: https://github.com/square/retrofit/issues/291

Il metodo suggerito da questa risposta è quello di creare un tipo personalizzato che ridefinisce il metodo toString(), perché Retrofit utilizza internamente String.valueOf(value) per convertire i parametri di query o di percorso per le stringhe.

Quindi, si potrebbe avere qualcosa di simile:

class Recipe { 
    public int id; 
    public String title; 

    @Override 
    public String toString() { 
    // You can use a GSON serialization here if you want 
    // This is not a robust implementation 
    return Integer.toString(id) + "-" + title; 
    } 
} 
+0

Apparentemente il supporto è stato aggiunto da allora. Vedi [risposta sotto] (http://stackoverflow.com/a/42459356/741217) –

0

È possibile utilizzare r etrofit.RestAdapter.Builder(). setConverter (...) per passare un convertitore json personalizzato.

+1

Grazie per il risposta rapida. Ho già impostato il convertitore. Il problema è che il convertitore viene utilizzato solo all'interno del corpo @.Ho bisogno della mia serializzazione all'interno della query @ – Frame91

3

Questo è ora possibile al momento della registrazione di un personalizzato Converter.Factory che l'override del metodo stringConverter, che viene chiamato durante la risoluzione dei parametri. Lo Github issue che @William faceva riferimento a 2 anni fa non sembra essere aggiornato da quando è stato aggiunto il supporto.

Metodo Javadoc:

Restituisce un convertitore per la conversione di tipo in una stringa, o null se il tipo non può essere gestito da questa fabbrica. Viene utilizzato per creare convertitori per i tipi specificati dai valori @Field, @FieldMap, @Header, @HeaderMap, @Path, @Query e @QueryMap.

L'esempio seguente delega a Gson, ma allo stesso modo è possibile applicare qualsiasi tipo di conversione ai parametri.

Esempio: GsonStringConverterFactory

class GsonStringConverterFactory 
    extends Converter.Factory { 

    private final transient Gson gson; 

    GsonStringConverterFactory(final Gson gson) { 

     this.gson = gson; 
    } 

    @Override 
    public Converter<?, String> stringConverter(final Type type, final Annotation[] annotations, final Retrofit retrofit) { 

     final TypeAdapter typeAdapter; 
     typeAdapter = gson.getAdapter(TypeToken.get(type)); 

     return new StringConverter<>(typeAdapter); 
    } 

    private static class StringConverter<T> 
      implements Converter<T, String> { 

     private final TypeAdapter<T> typeAdapter; 

     private StringConverter(final TypeAdapter<T> typeAdapter) { 

      this.typeAdapter = typeAdapter; 
     } 

     @Override 
     public String convert(final T value) 
       throws IOException { 

      /* This works in our case because parameters in this REST api are always some kind of scalar 
      * and the toJson method converts these to simple json types. */ 
      final String jsonValue; 
      jsonValue = typeAdapter.toJson(value)); 

      if (jsonValue.startsWith("\"") && jsonValue.endsWith("\"") { 
       /* Strip enclosing quotes for json String types */ 
       return jsonValue.substring(1, jsonValue.length() - 1); 
      } else { 
       return jsonValue; 
      } 
     } 
    } 
} 

Registrazione del convertitore:

Per registrare il convertitore personalizzato, il costruttore di retrofit potrebbe essere simile a questa:

new Retrofit.Builder().baseUrl(BASE_URL) 
          .addConverterFactory(GsonConverterFactory.create(gson)) 
          .addConverterFactory(new GsonStringConverterFactory(gson)) 
          .build();