2015-02-13 12 views
5

Wyobraźmy sobie następującą prośbę:Serializować Query parametr w Retrofit

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

chciałbym mieć toJSON (przepis), ale niestety moja prośba jest tylko wywołanie toString() dla mojego przepisu, który nie działa w ogóle.

Mogę zastąpić toString w przepisie, ale wolę ogólne rozwiązanie.

Nie mogę korzystać @Body jak trzeba określić, co mam na wysyłanie (muszę mieć „receptury = json (theRecipe)”.

ja również nie może zmienić serializacji dodać „przepis =” jak nie jestem za serwer.

Obecnie używam QueryMap mapie, gdzie mogę umieścić w odcinkach obiektu. Chociaż to działa, to nie jest bardzo miłe rozwiązanie moim zdaniem.

Czy mogę jakoś przechwycić przejściówkę?

Odpowiedz

6

Nie sądzę, że obsługuje to teraz w jakiś miły sposób. Zaznacz tę odpowiedź od jednego z autorów: https://github.com/square/retrofit/issues/291

Proponowana metoda od tej odpowiedzi jest stworzenie typ niestandardowy, który zastępuje metodę toString(), ponieważ Modernizacja wewnętrznie używa String.valueOf(value) konwertować parametry zapytania lub ścieżka do strun.

Tak, można mieć coś takiego:

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

Wygląda na to, że wsparcie zostało dodane od tego czasu. Patrz [odpowiedź poniżej] (http://stackoverflow.com/a/42459356/741217) –

0

Możesz użyć r etrofit.RestAdapter.Builder() .setConverter (...) aby przekazać niestandardowy konwerter json.

+1

Dzięki za szybka odpowiedź. Już ustawiłem konwerter. Problem polega na tym, że konwerter jest używany tylko wewnątrz @ Body.Potrzebuję mojej serializacji w ramach @ Query – Frame91

3

teraz jest to możliwe przy rejestracji zwyczaj Converter.Factory że przesłania metodę stringConverter, która jest wywoływana podczas rozwiązywania parametry. The Github issue, którego @William odniósł 2 lata temu, nie wydaje się być aktualizowany od czasu dodania obsługi.

Metoda Javadoc:

Zwraca Converter do konwersji do typu String lub null, jeśli typ może nie być obsługiwane przez dany zakład. Służy do tworzenia konwerterów dla typów określonych przez wartości @Field, @FieldMap, @Header, @HeaderMap, @Path, @Query i @QueryMap.

Poniższy przykład deleguje do Gson, ale w ten sam sposób do parametrów można zastosować każdy rodzaj konwersji.

Przykład: 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; 
      } 
     } 
    } 
} 

Rejestrowanie Przelicznik:

Aby zarejestrować niestandardową konwertera, twój Modernizacja budowniczy może wyglądać mniej więcej tak:

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