[英]Change default enum serialization & deserialization in gson
我正在以一種略微“不同”的方式使用Gson,我想知道以下是否可行......
我想更改枚舉的默認序列化/反序列化格式,以便它使用完全限定的類名,但在所述枚舉上保持對@SerializedName注釋的支持。 基本上,鑒於以下枚舉...
package com.example;
public class MyClass {
public enum MyEnum {
OPTION_ONE,
OPTION_TWO,
@SerializedName("someSpecialName")
OPTION_THREE
}
}
我想以下是真實的......
gson.toJson(MyEnum.OPTION_ONE) == "com.example.MyClass.MyEnum.OPTION_ONE"
&&
gson.toJson(MyEnum.OPTION_TWO) == "com.example.MyClass.MyEnum.OPTION_TWO"
&&
gson.toJson(MyEnum.OPTION_THREE) == "someSpecialName"
反之亦然。
(對於那些好奇的人,我正在嘗試構建一個小的lib,它允許我將android的intent的動作視為枚舉,這樣我就可以編寫switch語句而不是一堆丑陋的if-elses + string比較,我想支持注釋,以便我也可以在同一個枚舉中包含自定義的預先存在的動作字符串,如Intent.ACTION_VIEW等。
那么有人會知道是否可以注冊一個類型適配器,如果@SerializedName字段存在,它可以回退? 我是否只需要在自己的TypeAdapter中檢查該注釋?
提前致謝。
我為這個問題創建了非常好的解決方案:
package your.package.name
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class EnumAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
Class<? super T> rawType = type.getRawType();
if (rawType.isEnum()) {
return new EnumTypeAdapter<T>();
}
return null;
}
public class EnumTypeAdapter<T> extends TypeAdapter<T> {
public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
Enum<?> realEnums = Enum.valueOf(value.getClass().asSubclass(Enum.class), value.toString());
Field[] enumFields = realEnums.getClass().getDeclaredFields();
out.beginObject();
out.name("name");
out.value(realEnums.name());
for (Field enumField : enumFields) {
if (enumField.isEnumConstant() || enumField.getName().equals("$VALUES")) {
continue;
}
enumField.setAccessible(true);
try {
out.name(enumField.getName());
out.value(enumField.get(realEnums).toString());
} catch (Throwable th) {
out.value("");
}
}
out.endObject();
}
public T read(JsonReader in) throws IOException {
return null;
}
}
}
而且當然 :
new GsonBuilder().registerTypeAdapterFactory(new EnumAdapterFactory()).create();
希望這可以幫助 !
做了一些google-ing並找到了Gson的EnumTypeAdapter和相關AdapterFactory的來源: https : //code.google.com/p/google-gson/source/browse/trunk/gson/src/main/java/com/谷歌/ GSON /內部/結合/ TypeAdapters.java#717
從它的外觀來看,我實際上必須手動檢查@SerializedName屬性,但看起來很簡單。 我打算復制適配器和適配器工廠(幾乎逐行)並修改name
的默認值(第724行)以包含完整的類名。
生成的TypeAdapter看起來像這樣......
private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
private final Map<String, T> nameToConstant = new HashMap<String, T>();
private final Map<T, String> constantToName = new HashMap<T, String>();
public EnumTypeAdapter(Class<T> classOfT) {
try {
String classPrefix = classOfT.getName() + ".";
for (T constant : classOfT.getEnumConstants()) {
String name = constant.name();
SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class);
if (annotation != null) {
name = annotation.value();
} else {
name = classPrefix + name;
}
nameToConstant.put(name, constant);
constantToName.put(constant, name);
}
} catch (NoSuchFieldException e) {
throw new AssertionError();
}
}
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return nameToConstant.get(in.nextString());
}
public void write(JsonWriter out, T value) throws IOException {
out.value(value == null ? null : constantToName.get(value));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.