2016-03-04 7 views
6

मैं एक सरल enum है:रेट्रोफिट के माध्यम से @Query में कस्टम enum कैसे पास करें?

public enum Season { 
    @SerializedName("0") 
    AUTUMN, 
    @SerializedName("1") 
    SPRING; 
} 

कुछ संस्करण शुरू, GSON ऐसे enums पार्स करने में सक्षम हो गया। यह सुनिश्चित करने के लिए, मैंने यह किया:

final String s = gson.toJson(Season.AUTUMN); 

यह मेरी अपेक्षा के अनुसार काम करता है। आउटपुट "0" है। तो, मैं अपने रेट्रोफिट सेवाओं में इसका इस्तेमाल करने की कोशिश की:

@GET("index.php?page[api]=test") 
Observable<List<Month>> getMonths(@Query("season_lookup") Season season); 
/*...some files later...*/ 
service.getMonths(Season.AUTUMN); 

और यह भी उसके परिणाम के बारे में वास्तव में कुछ होने के लिए प्रवेश करने जोड़ा गया:

HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); 
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 

OkHttpClient httpClient = new OkHttpClient.Builder() 
     .addInterceptor(httpLoggingInterceptor) 
     .build(); 

लेकिन यह विफल रहा है। @Query ने पूरी तरह से @SerializedName को अनदेखा किया और इसके बजाय .toString() का उपयोग किया, इसलिए लॉग ने मुझे .../index.php?page[api]=test&season_lookup=AUTUMN दिखाया।

मैं रेट्रोफिट स्रोतों का पता लगाया और लाइनों के साथ फ़ाइल RequestFactoryParser पाया:

Converter<?, String> converter = 
    retrofit.stringConverter(parameterType, parameterAnnotations); 
action = new RequestAction.Query<>(name, converter, encoded); 

ऐसा लगता है, जैसे कि यह बिल्कुल enums के बारे में परवाह नहीं है। इन पंक्तियों से पहले, यह rawParameterType.isArray() का परीक्षण एक सरणी या Iterable.class.isAssignableFrom() और कुछ भी नहीं था।

रेट्रोफिट उदाहरण रचना है:

retrofit = new Retrofit.Builder() 
       .baseUrl(ApiConstants.API_ENDPOINT) 
       .client(httpClient) 
       .addConverterFactory(GsonConverterFactory.create(gson)) 
       .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
       .build(); 

gsonGsonBuilder().create() है। मैंने स्रोतों पर देखा, enums के लिए इसमें ENUM_TypeAdapters.ENUM_FACTORY पूर्वनिर्धारित है, इसलिए मैं इसे छोड़ देता हूं।


सवाल मेरे enums परtoString()का उपयोग कर रोकने के लिए और@SerializedNameउपयोग करने के लिए मैं क्या कर सकते हैं? मैं अन्य उद्देश्यों के लिएtoString()का उपयोग करता हूं।

+1

आप उचित कनवर्टर अपने रेट्रोफिट को जोड़ा गया है? https://github.com/square/retrofit/tree/master/retrofit-converters –

+1

ऐसा लगता है कि रेट्रोफिट

@Body
क्रमबद्ध करते समय जीसन का उपयोग करता है, लेकिन
@Query
नहीं, क्योंकि
@Body
के साथ यह सही तरीके से क्रमबद्ध है। –

+0

@ DawidSzydło, लेकिन क्या 'Enum ' के लिए कन्वर्टर जैसे कुछ लिखने का कोई तरीका है? मैं '@ SerializedName' – Nexen

उत्तर

6

जैसा कि @ DawidSzydło ने उल्लेख किया है, मैंने रेट्रोफिट में Gson उपयोग को गलत समझा। इसका उपयोग केवल प्रतिक्रिया/अनुरोध डीकोडिंग/एन्कोडिंग के लिए किया जाता है, लेकिन @Query/@Url/@Path e.t.c के लिए नहीं। उनके लिए, रेट्रोफिट किसी भी प्रकार को String में परिवर्तित करने के लिए Converter.Factory का उपयोग करता है। रेट्रोफिट सेवाओं को पास करते समय Enum के मान के रूप में @SerializedName का उपयोग कर ऑटो के लिए कोड यहां दिया गया है।

कनवर्टर:

public class EnumRetrofitConverterFactory extends Converter.Factory { 
    @Override 
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) { 
     Converter<?, String> converter = null; 
     if (type instanceof Class && ((Class<?>)type).isEnum()) { 
      converter = value -> EnumUtils.GetSerializedNameValue((Enum) value); 
     } 
     return converter; 
    } 
} 

EnumUtils:

public class EnumUtils { 
    @Nullable 
    static public <E extends Enum<E>> String GetSerializedNameValue(E e) { 
     String value = null; 
     try { 
      value = e.getClass().getField(e.name()).getAnnotation(SerializedName.class).value(); 
     } catch (NoSuchFieldException exception) { 
      exception.printStackTrace(); 
     } 
     return value; 
    } 
} 

रेट्रोफिट निर्माण:

retrofit = new Retrofit.Builder() 
     .baseUrl(ApiConstants.API_ENDPOINT) 
     .client(httpClient) 
     .addConverterFactory(GsonConverterFactory.create(gson)) 
     .addConverterFactory(new EnumRetrofitConverterFactory()) 
     .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
     .build(); 
+2

के लिए उसमें प्रतिबिंब का उपयोग करना चाहता हूं ठीक दिखता है, लेकिन यदि आप अन्य अनुरोधों में धारावाहिक नाम एनोटेशन के बिना enum का उपयोग करना चाहते हैं तो यह असफल हो जाएगा। असल में इसके लिए त्वरित समाधान होगा: आपके सहायक वर्ग में पकड़ने के लिए यदि कोई एनोटेशन उपयोग नहीं किया जाता है तो आपको मूल्य मूल्य को मूल्य मान निर्धारित करना चाहिए। –

संबंधित मुद्दे