Java 更改默认枚举序列化&;gson中的反序列化
我正在以一种稍微“不同”的方式使用Gson,我想知道下面是否可能 我想更改枚举的默认序列化/反序列化格式,以便它使用完全限定的类名,但在所述枚举上保持对@SerializedName注释的支持。基本上,给定以下枚举Java 更改默认枚举序列化&;gson中的反序列化,java,serialization,enums,gson,Java,Serialization,Enums,Gson,我正在以一种稍微“不同”的方式使用Gson,我想知道下面是否可能 我想更改枚举的默认序列化/反序列化格式,以便它使用完全限定的类名,但在所述枚举上保持对@SerializedName注释的支持。基本上,给定以下枚举 package com.example; public class MyClass { public enum MyEnum { OPTION_ONE, OPTION_TWO, @SerializedName("som
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"
反之亦然
(对于那些好奇的人,我正在尝试构建一个小库,它允许我将android的intent操作视为枚举,这样我就可以编写switch语句,而不是一堆丑陋的elses+字符串,并且我想支持注释,这样我还可以在同一个菜单中包含自定义的预先存在的操作字符串,如intent.action\u视图等。)m)
那么,有人知道如果存在@SerializedName字段,是否可以注册一个可以回退的类型适配器吗?我是否需要自己在自己的类型适配器中检查该注释
提前感谢。在谷歌上搜索了一下,找到了Gson的EnumTypeAdapter和相关AdapterFactory的源代码: 从外观上看,事实上,我必须手动检查@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));
}
}
私有静态最终类EnumTypeAdapter扩展了TypeAdapter{
私有最终映射nameToConstant=newhashmap();
私有最终映射constantToName=新HashMap();
公共EnumTypeAdapter(类ClassSoft){
试一试{
字符串classPrefix=classOfT.getName()+“;
对于(T常量:classOfT.getEnumConstants()){
字符串名称=常量。名称();
SerializedName annotation=ClassSoft.getField(名称).getAnnotation(SerializedName.class);
if(注释!=null){
name=annotation.value();
}否则{
name=classPrefix+name;
}
nameToConstant.put(名称,常量);
constantToName.put(常量,名称);
}
}捕获(无此字段例外){
抛出新的断言错误();
}
}
公共T读取(JsonReader in)引发IOException{
if(in.peek()==JsonToken.NULL){
in.nextNull();
返回null;
}
返回nameToConstant.get(in.nextString());
}
public void write(JsonWriter out,T值)抛出IOException{
out.value(value==null?null:constantToName.get(value));
}
}
我为这个问题创建了非常好的解决方案:
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();