javajsonxmlgson

How to get XmlEnumValue in gson conversions?


I use gson.toJson and gson.fromGson methods. I have a class like below.

@XmlType(name = "CBPR_CancellationReasonCode")
@XmlEnum
public enum CBPRCancellationReasonCode {

    DUPL("DUPL"),
    CUTA("CUTA"),
    UPAY("UPAY"),
    CUST("CUST"),
    CURR("CURR"),
    AGNT("AGNT"),
    TECH("TECH"),
    FRAD("FRAD"),
    COVR("COVR"),
    @XmlEnumValue("AM09")
    AM_09("AM09"),
    NARR("NARR");
    private final String value;

    CBPRCancellationReasonCode(String v) {
        value = v;
    }

    public String value() {
        return value;
    }

    public static CBPRCancellationReasonCode fromValue(String v) {
        for (CBPRCancellationReasonCode c: CBPRCancellationReasonCode.values()) {
            if (c.value.equals(v)) {
                return c;
            }
        }
        throw new IllegalArgumentException(v);
    }

}

I have problem converting values from xml to json or json to xml while using

@XmlEnumValue("AM09")
AM_09("AM09")

I expect to see "AM09" value but it takes AM_09.

How can I solve this problem?

Some parts of my code are as follows.

 Gson gson = new GsonBuilder().setFieldNamingStrategy(new XsdAnnotation()).setPrettyPrinting()
                .registerTypeHierarchyAdapter(XMLGregorianCalendar.class,
                        new XMLGregorianCalendarConverter.Serializer())
                .registerTypeHierarchyAdapter(XMLGregorianCalendar.class,
                        new XMLGregorianCalendarConverter.Deserializer())
                .create();

gson.toJson(testObject)

public class XsdAnnotation implements FieldNamingStrategy {

    @Override
    public String translateName(Field field) {
        XmlElement fieldNamingPolicyElement = field.getAnnotation(XmlElement.class);
        XmlAttribute fieldNamingPolicyAttribute = field.getAnnotation(XmlAttribute.class);

        return fieldNamingPolicyElement != null
                ? fieldNamingPolicyElement.name()
                : (fieldNamingPolicyAttribute != null ? fieldNamingPolicyAttribute.name() : field.getName());
    }

}

Solution

  • With @Vijay's guidance, my problem was solved with the following code.

    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.JsonToken;
    import com.google.gson.stream.JsonWriter;
    import jakarta.xml.bind.annotation.XmlEnumValue;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    public 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 {
                for (T constant : classOfT.getEnumConstants()) {
                    String name = constant.name();
                    XmlEnumValue annotation = classOfT.getField(name).getAnnotation(XmlEnumValue.class);
                    if (annotation != null) {
                        name = annotation.value();
                    }
                    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));
        }
    
        public static final TypeAdapterFactory ENUM_FACTORY = new TypeAdapterFactory() {
            @SuppressWarnings({"rawtypes", "unchecked"})
            @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
                Class<? super T> rawType = typeToken.getRawType();
                if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) {
                    return null;
                }
                if (!rawType.isEnum()) {
                    rawType = rawType.getSuperclass();
                }
                return (TypeAdapter<T>) new EnumTypeAdapter(rawType);
            }
        };
    }
    
    Gson gson = new GsonBuilder().setFieldNamingStrategy(new XsdAnnotation()).setPrettyPrinting()
                    .registerTypeHierarchyAdapter(XMLGregorianCalendar.class,
                            new XMLGregorianCalendarConverter.Serializer())
                    .registerTypeHierarchyAdapter(XMLGregorianCalendar.class,
                            new XMLGregorianCalendarConverter.Deserializer())
                    .registerTypeAdapterFactory(EnumTypeAdapter.ENUM_FACTORY)
                    .create();