2012-01-30 17 views
22

मैं एक enum है:GSON गैर केस संवेदनशील Enum Deserialization

enum Type { 
    LIVE, UPCOMING, REPLAY 
} 

और कुछ JSON:

{ 
    "type": "live" 
} 

और एक वर्ग:

class Event { 
    Type type; 
} 

जब मैं deserialize करने की कोशिश जेएसओएन, जीएसओएन का उपयोग करते हुए, मुझे टाइप फ़ील्ड के लिए null प्राप्त होता है, क्योंकि टाइप फ़ील्ड के मामले में JSON enum से मेल नहीं खाता है।

Events events = new Gson().fromJson(json, Event.class); 

अगर मैं निम्नलिखित करने के लिए enum बदलने के लिए, तो सब ठीक काम करता है:

enum Type { 
    live, upcoming, replay 
} 

हालांकि, मैं सभी अपरकेस के रूप में enum स्थिरांक छोड़ने के लिए चाहते हैं।

मुझे लगता है कि मुझे एडाप्टर लिखने की ज़रूरत है, लेकिन मुझे कोई अच्छा दस्तावेज या उदाहरण नहीं मिला है।

सबसे अच्छा समाधान क्या है?


संपादित करें:

मैं एक JsonDeserializer काम कर पाने में सक्षम था। हालांकि इसे लिखने का एक और सामान्य तरीका है, क्योंकि हर बार इसे लिखना दुर्भाग्यपूर्ण होगा क्योंकि एनम मूल्यों और जेएसओएन तारों के बीच एक मामला गलत मिलान है।

protected static class TypeCaseInsensitiveEnumAdapter implements JsonDeserializer<Type> { 
    @Override 
    public Type deserialize(JsonElement json, java.lang.reflect.Type classOfT, JsonDeserializationContext context) 
      throws JsonParseException {   
     return Type.valueOf(json.getAsString().toUpperCase()); 
    } 
} 

उत्तर

18

सुविधाजनक आप के लिए, यह बहुत TypeAdapterFactory's Javadoc में दिए गए उदाहरण के करीब है:

public class LowercaseEnumTypeAdapterFactory implements TypeAdapterFactory { 
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { 
    Class<T> rawType = (Class<T>) type.getRawType(); 
    if (!rawType.isEnum()) { 
     return null; 
    } 

    final Map<String, T> lowercaseToConstant = new HashMap<String, T>(); 
    for (T constant : rawType.getEnumConstants()) { 
     lowercaseToConstant.put(toLowercase(constant), constant); 
    } 

    return new TypeAdapter<T>() { 
     public void write(JsonWriter out, T value) throws IOException { 
     if (value == null) { 
      out.nullValue(); 
     } else { 
      out.value(toLowercase(value)); 
     } 
     } 

     public T read(JsonReader reader) throws IOException { 
     if (reader.peek() == JsonToken.NULL) { 
      reader.nextNull(); 
      return null; 
     } else { 
      return lowercaseToConstant.get(reader.nextString()); 
     } 
     } 
    }; 
    } 

    private String toLowercase(Object o) { 
    return o.toString().toLowerCase(Locale.US); 
    } 
} 
+0

ध्यान दें कि उपरोक्त कोड _serializes_ लोअरकेस एनम मान और _deserializes_ केवल लोअरकेस मानों के सटीक मिलान के लिए सही है। केस-असंवेदनशील deserialization प्रदर्शन करने के लिए, पढ़ने() विधि संशोधित करें: 'वापसी लोअरकेस ToConstant.get (toLowercase (reader.nextString()))। और मूल मामले का उपयोग करके क्रमबद्ध करने के लिए, लिखें() विधि संशोधित करें: 'out.value (value.toString())'। – nivs

86

एक आसान तरीका मैंने पाया (अभी) यह करने के लिए @SerializedName एनोटेशन का प्रयोग है। मैं EnumTest.java यहाँ में यह पाया (Gender ln 195 के आसपास वर्ग):

https://code.google.com/p/google-gson/source/browse/trunk/gson/src/test/java/com/google/gson/functional/EnumTest.java?r=1230

मतलब यह है कि अपने प्रकार के सभी के रूप में किया जा रहा है "असंवेदनशील मामला"

public enum Type { 
    @SerializedName("live") 
    LIVE, 

    @SerializedName("upcoming") 
    UPCOMING, 

    @SerializedName("replay") 
    REPLAY; 
} 
करने का विरोध किया लोअरकेस के रूप में आ जाएगा

यह ऐसा करने का सबसे सरल और सबसे सामान्य तरीका था। उम्मीद है कि यह आपकी मदद करता है।

+2

अगर मैं आपको और अधिक अंक भेज सकता हूं ... या जैसे, एक बियर या लॉलीपॉप। – Spedge

+0

यह वास्तव में साफ है। एक संपूर्ण एंड्रॉइड टीम के नाम पर: thx :) – balazsbalazs

+2

यह स्वीकार्य उत्तर होना चाहिए –

5

यह एक नहीं बल्कि पुराने सवाल है, लेकिन उसे स्वीकार जवाब मेरे लिए काम नहीं किया था, और @SerializedName का उपयोग कर पर्याप्त क्योंकि मुझे यकीन है कि मैं "value", "Value" और "VALUE" मिलान कर सकते हैं बनाना चाहते नहीं है।

public class UppercaseEnumAdapter implements JsonDeserializer<Enum> { 
    @Override 
    public Enum deserialize(JsonElement json, java.lang.reflect.Type type, JsonDeserializationContext context) 
      throws JsonParseException { 
     try { 
      if(type instanceof Class && ((Class<?>) type).isEnum()) 
       return Enum.valueOf((Class<Enum>) type, json.getAsString().toUpperCase()); 
      return null; 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 
} 

और यह उपयोग करने के लिए:

मैं कोड सवाल में तैनात के आधार पर एक सामान्य एडाप्टर बनाने में कामयाब रहे

GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.registerTypeAdapter(MyEnum.class, new UppercaseEnumAdapter()); 
Gson gson = gsonBuilder.create(); 
6

अब आप इस तरह @SerializedName के लिए अनेक मान जोड़ सकते हैं :

public enum Type { 
    @SerializedName(value = "live", alternate = {"LIVE"}) 
    LIVE, 

    @SerializedName(value = "upcoming", alternate = {"UPCOMING"}) 
    UPCOMING, 

    @SerializedName(value = "replay", alternate = {"REPLAY"}) 
    REPLAY; 
} 

मुझे लगता है कि यह आपके लिए थोड़ा देर हो चुकी है, लेकिन मुझे उम्मीद है कि यह किसी और की मदद करेगा!

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