Java GSON不区分大小写的枚举反序列化

Java GSON不区分大小写的枚举反序列化,java,gson,json-deserialization,Java,Gson,Json Deserialization,我有一个枚举: 枚举类型{ 直播、即将播出、重播 } 还有一些JSON: { "type": "live" } 还有一节课: 类事件{ 类型; } 当我尝试使用GSON反序列化JSON时,我收到事件类型字段的null,因为JSON中类型字段的大小写与枚举的大小写不匹配 Events-Events=new Gson().fromJson(json,Event.class); 如果将枚举更改为以下值,则所有操作都正常: 枚举类型{ 直播、即将播出、重播 } 但是,我想将枚举常量保留

我有一个枚举:

枚举类型{
直播、即将播出、重播
}
还有一些JSON:

{
    "type": "live"
}
还有一节课:

类事件{
类型;
}
当我尝试使用GSON反序列化JSON时,我收到
事件
类型字段的
null
,因为JSON中类型字段的大小写与枚举的大小写不匹配

Events-Events=new Gson().fromJson(json,Event.class);
如果将枚举更改为以下值,则所有操作都正常:

枚举类型{
直播、即将播出、重播
}
但是,我想将枚举常量保留为全部大写

我假设我需要编写一个适配器,但还没有找到任何好的文档或示例

最好的解决方案是什么


编辑:

我能够让JsonDeserializer工作。但是,是否有更通用的方法来编写此代码,因为每次枚举值和JSON字符串之间出现大小写不匹配时都必须编写此代码是很不幸的

受保护的静态类TypeCaseInsensitiveEnumAdapter实现JsonDeserializer{
@凌驾
公共类型反序列化(JsonElement json、java.lang.reflect.Type ClassSoft、JsonDeserializationContext)
抛出JsonParseException{
返回类型.valueOf(json.getAsString().toUpperCase());
}
}

对于您来说,这与中给出的示例非常接近:

公共类CaseInsensitiveEnumTypeAdapterFactory实现TypeAdapterFactory{
公共类型适配器创建(Gson Gson,TypeToken类型){
类rawType=(类)type.getRawType();
如果(!rawType.isEnum()){
返回null;
}
final Map lowercaseToConstant=新HashMap();
对于(T常量:rawType.getEnumConstants()){
lowercasetoctant.put(toLowercase(constant),constant);
}
返回新的TypeAdapter(){
public void write(JsonWriter out,T值)抛出IOException{
如果(值==null){
out.nullValue();
}否则{
out.value(toLowercase(value));
}
}
公共T读取(JsonReader读取器)引发IOException{
if(reader.peek()==JsonToken.NULL){
reader.nextNull();
返回null;
}否则{
返回LowercaseToctant.get(toLowercase(reader.nextString());
}
}
};
}
私有字符串toLowercase(对象o){
返回o.toString().toLowerCase(Locale.US);
}
}
我(刚才)发现的一种更简单的方法是使用
@SerializedName
注释。我在这里的
EnumTest.java
中找到了它(195年左右的
Gender
类):

这假设您的所有类型都是小写的,而不是“不区分大小写”

公共枚举类型{
@序列化名称(“live”)
居住
@SerializedName(“即将发布”)
即将到来的
@SerializedName(“重播”)
重播;
}

这是我发现的最简单、最通用的方法。希望能对您有所帮助。

这是一个相当老的问题,但公认的答案对我来说并不适用,使用
@SerializedName
是不够的,因为我想确保我可以匹配
“value”
“value”
“value”

我根据问题中发布的代码制作了一个通用适配器:

公共类UppercaseEnumAdapter实现JsonDeserializer{
@凌驾
公共枚举反序列化(JsonElement json、java.lang.reflect.Type、JsonDeserializationContext)
抛出JsonParseException{
试一试{
if(type instanceof Class&((Class)type).isEnum())
返回Enum.valueOf((类)类型,json.getAsString().toUpperCase());
返回null;
}捕获(例外e){
e、 printStackTrace();
返回null;
}
}
}
使用它:

GsonBuilder GsonBuilder=new GsonBuilder();
gsonBuilder.registerTypeAdapter(MyEnum.class,新的UppercaseEnumAdapter());
Gson-Gson=gsonBuilder.create();

现在您可以像这样为
@SerializedName
添加多个值:

公共枚举类型{
@SerializedName(value=“live”,alternate={“live”})
居住
@SerializedName(value=“即将到来”,alternate={“即将到来”})
即将到来的
@SerializedName(value=“replay”,alternate={“replay”})
重播;
}

我想这对你来说有点晚了,但我希望它能帮助其他人

要是我能给你更多的分数就好了……或者像,一杯啤酒或者一个棒棒糖。这真是太棒了。以整个安卓团队的名义:thx:)但愿我以前知道这件事!是的,它看起来很简单,但它无法避免字符串的冗余重复。我希望Gson能有类似于
小写的东西,带有下划线
枚举的字段命名策略…它整洁、清晰、有用,但是,它不是真正的“不区分大小写”,是吗?因为它只能以小写形式解析项,所以如果遇到类似“liVE”的情况,它也无法解析。请注意,上面的代码序列化了小写枚举值,并仅针对小写值的精确匹配正确反序列化。要执行不区分大小写的反序列化,请修改read()方法:
返回LowercaseToctant.get(toLowercase(reader.nextString())
。要使用原始大小写进行序列化,请修改write()方法:
out.value(value.toString())
。这就是实现“不区分大小写”的真正原因。这应该是公认的答案。