2012-01-30 11 views
22

私が列挙持っている:私は逆シリアル化しようとするとGSON非大文字と小文字を区別する列挙型デシリアライズ

class Event { 
    Type type; 
} 

enum Type { 
    LIVE, UPCOMING, REPLAY 
} 

そして、いくつかのJSON:

{ 
    "type": "live" 
} 

とクラスをJSONは、GSONを使用して、のEventタイプのフィールドを受け取ります。これは、タイプフィールドがJSONはenumのJSONと一致しません。

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

私は次のように列挙型を変更する場合は、すべてが正常に動作します:

enum Type { 
    live, upcoming, replay 
} 

しかし、私はすべて大文字としてenum定数を残したいと思います。

私はアダプタを書く必要があると仮定していますが、適切な文書や例は見つかりませんでした。

最適なソリューションは何ですか?


編集:

私はJsonDeserializerの作業を取得することができました。列挙型の値とJSON文字列の間に大文字と小文字の不一致があるたびにこれを書く必要があるので、これを書くためのより一般的な方法がありますか?

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

上記のコードは、小文字のEnum値を_serializes_し、小文字の値と完全に一致する場合にのみ_deserializes_することに注意してください。 大文字と小文字を区別しないデシリアライズを実行するには、read()メソッドを変更します。 'return lowercaseToConstant.get(toLowercase(reader.nextString()))'。 元のケースを使用してシリアル化するには、write()メソッドを変更します。 'out.value(value.toString())'。 – nivs

86

簡単な方法は、@SerializedNameアノテーションを使用することです。私はここEnumTest.javaでそれを見つけた(LN 195周りGenderクラス):

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

私は"value""Value""VALUE"と一致することを確認したいので、これはかなり古い質問ですが、受け入れられた回答は私にとっては役に立たず、@SerializedNameを使用するだけでは不十分です。

私は疑問に投稿されたコードに基づいて、一般的なアダプタ作るために管理:

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

私はそれがあなたに少し遅れたと思うが、他の誰かを助けることを望む!

関連する問題