You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Gson序列化/反序列化中获取XmlEnumValue值?

问题原因

你当前的XsdAnnotation仅处理类字段的命名映射,但Gson默认对枚举的序列化逻辑是直接输出枚举常量的名称(比如AM_09),不会读取@XmlEnumValue注解或枚举类中自定义的value()方法返回值,因此导致序列化结果不符合预期。

解决方案

需要自定义Gson的枚举类型适配器,覆盖默认的枚举序列化/反序列化逻辑,让Gson使用枚举的value()返回值(或@XmlEnumValue注解值)进行转换。

方案1:针对特定枚举的极简适配器

因为你的CBPRCancellationReasonCode已经实现了value()返回目标字符串,且提供了fromValue()方法用于反向解析,直接基于这两个方法写适配器即可:

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;

public class CBPRCancellationReasonCodeAdapter extends TypeAdapter<CBPRCancellationReasonCode> {
    @Override
    public void write(JsonWriter out, CBPRCancellationReasonCode value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        // 序列化时输出枚举的value()返回值
        out.value(value.value());
    }

    @Override
    public CBPRCancellationReasonCode read(JsonReader in) throws IOException {
        String value = in.nextString();
        // 反序列化时调用枚举自带的fromValue方法
        return CBPRCancellationReasonCode.fromValue(value);
    }
}

然后在创建Gson实例时注册这个适配器:

Gson gson = new GsonBuilder()
        .setFieldNamingStrategy(new XsdAnnotation())
        .setPrettyPrinting()
        .registerTypeHierarchyAdapter(XMLGregorianCalendar.class, new XMLGregorianCalendarConverter.Serializer())
        .registerTypeHierarchyAdapter(XMLGregorianCalendar.class, new XMLGregorianCalendarConverter.Deserializer())
        .registerTypeAdapter(CBPRCancellationReasonCode.class, new CBPRCancellationReasonCodeAdapter()) // 注册枚举适配器
        .create();

方案2:通用枚举适配器(支持所有带@XmlEnumValue的枚举)

如果需要处理多个带@XmlEnumValue注解的枚举,可以写一个通用的适配器工厂,自动识别并处理这类枚举:

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 javax.xml.bind.annotation.XmlEnumValue;
import java.io.IOException;
import java.lang.reflect.Field;

public class EnumXmlAdapterFactory implements TypeAdapterFactory {
    @Override
    @SuppressWarnings("unchecked")
    public <T> TypeAdapter<T> create(com.google.gson.Gson gson, TypeToken<T> type) {
        Class<T> rawType = (Class<T>) type.getRawType();
        if (!rawType.isEnum()) {
            return null; // 仅处理枚举类型
        }

        return new TypeAdapter<T>() {
            @Override
            public void write(JsonWriter out, T value) throws IOException {
                if (value == null) {
                    out.nullValue();
                    return;
                }
                Enum<?> enumValue = (Enum<?>) value;
                // 优先读取@XmlEnumValue注解的值
                try {
                    Field field = rawType.getField(enumValue.name());
                    XmlEnumValue annotation = field.getAnnotation(XmlEnumValue.class);
                    if (annotation != null) {
                        out.value(annotation.value());
                        return;
                    }
                } catch (NoSuchFieldException ignored) {}
                
                // 没有注解则尝试调用value()方法
                try {
                    String enumValueStr = (String) rawType.getMethod("value").invoke(value);
                    out.value(enumValueStr);
                } catch (Exception ignored) {
                    // 兜底使用枚举名称
                    out.value(enumValue.name());
                }
            }

            @Override
            public T read(JsonReader in) throws IOException {
                String value = in.nextString();
                if (value == null) {
                    return null;
                }
                // 优先调用枚举的fromValue方法
                try {
                    return (T) rawType.getMethod("fromValue", String.class).invoke(null, value);
                } catch (Exception e) {
                    // 遍历枚举常量匹配注解值或value()返回值
                    for (T enumConstant : rawType.getEnumConstants()) {
                        Enum<?> enumValue = (Enum<?>) enumConstant;
                        // 匹配@XmlEnumValue
                        try {
                            Field field = rawType.getField(enumValue.name());
                            XmlEnumValue annotation = field.getAnnotation(XmlEnumValue.class);
                            if (annotation != null && annotation.value().equals(value)) {
                                return enumConstant;
                            }
                        } catch (NoSuchFieldException ignored) {}
                        // 匹配value()返回值
                        try {
                            String enumValueStr = (String) rawType.getMethod("value").invoke(enumConstant);
                            if (enumValueStr.equals(value)) {
                                return enumConstant;
                            }
                        } catch (Exception ignored) {}
                        // 兜底匹配枚举名称
                        if (enumValue.name().equals(value)) {
                            return enumConstant;
                        }
                    }
                    throw new IllegalArgumentException("无匹配的枚举常量: " + rawType.getName() + "." + value);
                }
            }
        };
    }
}

注册方式:

Gson gson = new GsonBuilder()
        .setFieldNamingStrategy(new XsdAnnotation())
        .setPrettyPrinting()
        .registerTypeHierarchyAdapter(XMLGregorianCalendar.class, new XMLGregorianCalendarConverter.Serializer())
        .registerTypeHierarchyAdapter(XMLGregorianCalendar.class, new XMLGregorianCalendarConverter.Deserializer())
        .registerTypeAdapterFactory(new EnumXmlAdapterFactory()) // 注册通用枚举适配器工厂
        .create();

内容的提问来源于stack exchange,提问作者Uğur Yeşilyurt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:07:06