如何使用Gson对带匿名子类的枚举类型进行序列化与反序列化
问题根因
registerTypeAdapter仅对严格匹配指定类的对象生效,UNKNOWN枚举实例因为重写了getStatusOld方法,属于Status的匿名子类实例,序列化时Gson没有匹配到你注册的Status类适配器,直接走默认枚举序列化逻辑,输出了枚举的name()值"UNKNOWN",而非你预期的"del"。- 反序列化时拿到的输入字符串是
"UNKNOWN",你的typeOf方法仅匹配枚举内置的name字段和getStatusOld返回值,无法匹配"UNKNOWN",因此抛出异常。
解决方案
方案一:使用继承树适配器注册(改动最小)
将registerTypeAdapter替换为registerTypeHierarchyAdapter,该方法会为指定类及其所有子类注册统一的序列化/反序列化逻辑,覆盖匿名子类场景:
Gson gson = new GsonBuilder() // 替换为继承树注册方法 .registerTypeHierarchyAdapter(Status.class, new GsonStatusEnumDeserializer()) .registerTypeHierarchyAdapter(Status.class, new GsonStatusEnumSerializer()) .create();
改完即可正常运行,无需修改其他代码。
方案二:使用Gson注解实现(更简洁,无需自定义适配器)
直接在枚举类上加Gson自带的序列化/反序列化注解,无需单独维护自定义适配器类:
import com.google.gson.annotations.JsonCreator; import com.google.gson.annotations.JsonValue; public enum Status { ONLINE("online"), OFFLINE("offline"), UNKNOWN("del") { @Override public String getStatusOld() { return "off"; } }; private final String name; Status(String name) { this.name = name; } public String getStatusOld() { return name; } // 序列化时使用该方法的返回值作为输出 @JsonValue public String toString() { return name; } // 反序列化时Gson自动调用该方法匹配枚举值 @JsonCreator public static Status typeOf(String name) { if (!StringUtils.isEmpty(name)) { for (Status type : values()) { if (type.name.equalsIgnoreCase(name)) { return type; } if (type.getStatusOld().equalsIgnoreCase(name)) { return type; } } } throw new IllegalArgumentException("Unknown status type: " + name); } }
改完后直接使用默认Gson实例即可,无需注册任何适配器:
Gson gson = new Gson();
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

