使用JAXB和moxy进行自定义枚举封送处理

使用JAXB和moxy进行自定义枚举封送处理,jaxb,marshalling,moxy,Jaxb,Marshalling,Moxy,我在使用Moxy和JSON进行自定义枚举封送时遇到一些问题。我的用例是,我有一个大型对象模型,其中包括通常应该提供正常枚举值、“代码”和描述的枚举。该数据源只有“代码”,因此我需要能够仅使用代码(例如 {“companyCode”:{“code”:“PI”} 但是,我还应该能够对所有三个字段进行封送和解封送: {"companyCode": {"value":"Private", "code":"PI","description": "Private Ins" } } 我使用

我在使用Moxy和JSON进行自定义枚举封送时遇到一些问题。我的用例是,我有一个大型对象模型,其中包括通常应该提供正常枚举值、“代码”和描述的枚举。该数据源只有“代码”,因此我需要能够仅使用代码(例如

{“companyCode”:{“code”:“PI”}

但是,我还应该能够对所有三个字段进行封送和解封送:

{"companyCode":
  {"value":"Private",
  "code":"PI","description":
  "Private Ins"
  }
}

我使用的适配器如下所示:

public class CodeEnumXmlAdapter<E extends Enum<E> & CodeEnum> extends XmlAdapter<CodeEnumImpl,E> {

    public static <T extends Enum<T> & CodeEnum> T getFromName(Class<T> clazz, String name) {
        if (name == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (name.equals(t.name())) {
                return t;
            }
        }

        return null;
    }
    public static <T extends Enum<T> & CodeEnum> T getFromCode(Class<T> clazz, String code) {
        if (code == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (code.equals(t.getCode())) {
                return t;
            }
        }

        return null;
    }
    public static <T extends Enum<T> & CodeEnum> T getFromString(Class<T> clazz, String aString) {
        if (aString == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (aString.equals(t.getCode()) || aString.equals(t.name()) || aString.equals(t.getDescription())) {
                return t;
            }
        }

        return null;
    }

    @Override
    public E unmarshal(CodeEnumImpl value) throws Exception {
        if (value == null) return null;

        String valueString = value.getValue();
        if (valueString == null)
            valueString = value.getCode();
        if (valueString == null)
            valueString = value.getDescription();
        if (valueString == null)
            return null;

        Type generic = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return getFromString((Class<E>)generic, valueString);
    }

    @Override
    public CodeEnumImpl marshal(E value) throws Exception {
        return value == null ? null : new CodeEnumImpl(value);
    }
}
import org.apache.commons.lang3.StringUtils;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(CompanyCode.Adapter.class)
public enum CompanyCode implements CodeEnum {

    // Changed "Commmercial" to "Client" based on inputs from ...Greg, Tamil
    Client("CM", "Client"), Medicare("MC", "Medicare"), Medicaid("MD",
            "Medicaid"), Private("PI", "Private Ins"), Patient("PT", "Patient");

    private String code;
    private String description;

    private CompanyCode(String code, String label) {
        this.code = code;
        this.description = label;
    }

    public String getDescription() {
        return description;
    }

    public String getCode() {
        return code;
    }

    public static CompanyCode fromCode(String code) {
        if (StringUtils.isEmpty(code)) {
            return null;
        }

        for (CompanyCode freq : values()) {
            if (freq.getCode().equalsIgnoreCase(code)) {
                return freq;
            }
        }
        throw new IllegalArgumentException("Invalid CompanyCode code: " + code);
    }

    public String toString() {
        return description;
    }

    public static class Adapter extends CodeEnumXmlAdapter<CompanyCode> {}
}
import javax.xml.bind.annotation.XmlElement;

/**
 * Created by Jeffrey Hoffman on 6/24/2015.
 */
public class CodeEnumImpl  {
    String value;
    String description;
    String code;

    public CodeEnumImpl() {

    }
    public <E extends Enum<E> & CodeEnum> CodeEnumImpl(E value) {
        if (value != null) {
            this.value = value.name();
            this.description = value.getDescription();
            this.code = value.getCode();
        }
    }

    @XmlElement
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @XmlElement
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @XmlElement
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Override
    public String toString() {
        return value == null ? null : value.toString();
    }
}
公共类CodeEnumXmlAdapter扩展XmlAdapter{
公共静态T getFromName(类clazz,字符串名){
if(name==null)返回null;
T[]value=clazz.getEnumConstants();
for(T:值){
if(name.equals(t.name())){
返回t;
}
}
返回null;
}
公共静态T getFromCode(类clazz,字符串代码){
if(code==null)返回null;
T[]value=clazz.getEnumConstants();
for(T:值){
if(code.equals(t.getCode())){
返回t;
}
}
返回null;
}
公共静态T getFromString(类clazz,字符串aString){
if(aString==null)返回null;
T[]value=clazz.getEnumConstants();
for(T:值){
if(aString.equals(t.getCode())| | aString.equals(t.name())| | aString.equals(t.getDescription()){
返回t;
}
}
返回null;
}
@凌驾
public E unmarshal(CodeEnumImpl值)引发异常{
if(value==null)返回null;
String valueString=value.getValue();
if(valueString==null)
valueString=value.getCode();
if(valueString==null)
valueString=value.getDescription();
if(valueString==null)
返回null;
类型generic=((ParameteredType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
返回getFromString((类)泛型,valueString);
}
@凌驾
public CodeEnumImpl封送处理(E值)引发异常{
返回值==null?null:新的CodeEnumImpl(值);
}
}
这将从如下所示的枚举中转换:

public class CodeEnumXmlAdapter<E extends Enum<E> & CodeEnum> extends XmlAdapter<CodeEnumImpl,E> {

    public static <T extends Enum<T> & CodeEnum> T getFromName(Class<T> clazz, String name) {
        if (name == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (name.equals(t.name())) {
                return t;
            }
        }

        return null;
    }
    public static <T extends Enum<T> & CodeEnum> T getFromCode(Class<T> clazz, String code) {
        if (code == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (code.equals(t.getCode())) {
                return t;
            }
        }

        return null;
    }
    public static <T extends Enum<T> & CodeEnum> T getFromString(Class<T> clazz, String aString) {
        if (aString == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (aString.equals(t.getCode()) || aString.equals(t.name()) || aString.equals(t.getDescription())) {
                return t;
            }
        }

        return null;
    }

    @Override
    public E unmarshal(CodeEnumImpl value) throws Exception {
        if (value == null) return null;

        String valueString = value.getValue();
        if (valueString == null)
            valueString = value.getCode();
        if (valueString == null)
            valueString = value.getDescription();
        if (valueString == null)
            return null;

        Type generic = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return getFromString((Class<E>)generic, valueString);
    }

    @Override
    public CodeEnumImpl marshal(E value) throws Exception {
        return value == null ? null : new CodeEnumImpl(value);
    }
}
import org.apache.commons.lang3.StringUtils;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(CompanyCode.Adapter.class)
public enum CompanyCode implements CodeEnum {

    // Changed "Commmercial" to "Client" based on inputs from ...Greg, Tamil
    Client("CM", "Client"), Medicare("MC", "Medicare"), Medicaid("MD",
            "Medicaid"), Private("PI", "Private Ins"), Patient("PT", "Patient");

    private String code;
    private String description;

    private CompanyCode(String code, String label) {
        this.code = code;
        this.description = label;
    }

    public String getDescription() {
        return description;
    }

    public String getCode() {
        return code;
    }

    public static CompanyCode fromCode(String code) {
        if (StringUtils.isEmpty(code)) {
            return null;
        }

        for (CompanyCode freq : values()) {
            if (freq.getCode().equalsIgnoreCase(code)) {
                return freq;
            }
        }
        throw new IllegalArgumentException("Invalid CompanyCode code: " + code);
    }

    public String toString() {
        return description;
    }

    public static class Adapter extends CodeEnumXmlAdapter<CompanyCode> {}
}
import javax.xml.bind.annotation.XmlElement;

/**
 * Created by Jeffrey Hoffman on 6/24/2015.
 */
public class CodeEnumImpl  {
    String value;
    String description;
    String code;

    public CodeEnumImpl() {

    }
    public <E extends Enum<E> & CodeEnum> CodeEnumImpl(E value) {
        if (value != null) {
            this.value = value.name();
            this.description = value.getDescription();
            this.code = value.getCode();
        }
    }

    @XmlElement
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @XmlElement
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @XmlElement
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Override
    public String toString() {
        return value == null ? null : value.toString();
    }
}
import org.apache.commons.lang3.StringUtils;
导入javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlJavaTypeAdapter(CompanyCode.Adapter.class)
公共枚举公司代码实现CodeEnum{
//根据泰米尔…格雷格的输入,将“商业”改为“客户”
客户(“CM”、“客户”)、医疗保险(“MC”、“医疗保险”)、医疗补助(“MD”,
“医疗补助”)、私人(“PI”、“私人Ins”)、患者(“PT”、“患者”);
私有字符串码;
私有字符串描述;
私有公司代码(字符串代码、字符串标签){
this.code=代码;
本说明=标签;
}
公共字符串getDescription(){
返回说明;
}
公共字符串getCode(){
返回码;
}
公共静态公司代码fromCode(字符串代码){
if(StringUtils.isEmpty(代码)){
返回null;
}
对于(公司代码频率:值()){
if(freq.getCode().equalsIgnoreCase(代码)){
返回频率;
}
}
抛出新的IllegalArgumentException(“无效的公司代码:”+代码);
}
公共字符串toString(){
返回说明;
}
公共静态类适配器扩展了CodeEnumXmlAdapter{}
}
使用和中间类型如下:

public class CodeEnumXmlAdapter<E extends Enum<E> & CodeEnum> extends XmlAdapter<CodeEnumImpl,E> {

    public static <T extends Enum<T> & CodeEnum> T getFromName(Class<T> clazz, String name) {
        if (name == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (name.equals(t.name())) {
                return t;
            }
        }

        return null;
    }
    public static <T extends Enum<T> & CodeEnum> T getFromCode(Class<T> clazz, String code) {
        if (code == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (code.equals(t.getCode())) {
                return t;
            }
        }

        return null;
    }
    public static <T extends Enum<T> & CodeEnum> T getFromString(Class<T> clazz, String aString) {
        if (aString == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (aString.equals(t.getCode()) || aString.equals(t.name()) || aString.equals(t.getDescription())) {
                return t;
            }
        }

        return null;
    }

    @Override
    public E unmarshal(CodeEnumImpl value) throws Exception {
        if (value == null) return null;

        String valueString = value.getValue();
        if (valueString == null)
            valueString = value.getCode();
        if (valueString == null)
            valueString = value.getDescription();
        if (valueString == null)
            return null;

        Type generic = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return getFromString((Class<E>)generic, valueString);
    }

    @Override
    public CodeEnumImpl marshal(E value) throws Exception {
        return value == null ? null : new CodeEnumImpl(value);
    }
}
import org.apache.commons.lang3.StringUtils;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(CompanyCode.Adapter.class)
public enum CompanyCode implements CodeEnum {

    // Changed "Commmercial" to "Client" based on inputs from ...Greg, Tamil
    Client("CM", "Client"), Medicare("MC", "Medicare"), Medicaid("MD",
            "Medicaid"), Private("PI", "Private Ins"), Patient("PT", "Patient");

    private String code;
    private String description;

    private CompanyCode(String code, String label) {
        this.code = code;
        this.description = label;
    }

    public String getDescription() {
        return description;
    }

    public String getCode() {
        return code;
    }

    public static CompanyCode fromCode(String code) {
        if (StringUtils.isEmpty(code)) {
            return null;
        }

        for (CompanyCode freq : values()) {
            if (freq.getCode().equalsIgnoreCase(code)) {
                return freq;
            }
        }
        throw new IllegalArgumentException("Invalid CompanyCode code: " + code);
    }

    public String toString() {
        return description;
    }

    public static class Adapter extends CodeEnumXmlAdapter<CompanyCode> {}
}
import javax.xml.bind.annotation.XmlElement;

/**
 * Created by Jeffrey Hoffman on 6/24/2015.
 */
public class CodeEnumImpl  {
    String value;
    String description;
    String code;

    public CodeEnumImpl() {

    }
    public <E extends Enum<E> & CodeEnum> CodeEnumImpl(E value) {
        if (value != null) {
            this.value = value.name();
            this.description = value.getDescription();
            this.code = value.getCode();
        }
    }

    @XmlElement
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @XmlElement
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @XmlElement
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Override
    public String toString() {
        return value == null ? null : value.toString();
    }
}
import javax.xml.bind.annotation.xmlement;
/**
*杰弗里·霍夫曼于2015年6月24日创作。
*/
公共类CodeEnumImpl{
字符串值;
字符串描述;
字符串代码;
公共代码EnumImpl(){
}
公共代码EnumImpl(E值){
if(值!=null){
this.value=value.name();
this.description=value.getDescription();
this.code=value.getCode();
}
}
@XmlElement
公共字符串getValue(){
返回值;
}
公共void设置值(字符串值){
这个值=值;
}
@XmlElement
公共字符串getDescription(){
返回说明;
}
公共void集合描述(字符串描述){
this.description=描述;
}
@XmlElement
公共字符串getCode(){
返回码;
}
公共无效设置码(字符串码){
this.code=代码;
}
@凌驾
公共字符串toString(){
返回值==null?null:value.toString();
}
}
这在直截了当的XML和JAXB中工作得很好。但是,当我尝试使用Moxy时,会出现如下异常:

public class CodeEnumXmlAdapter<E extends Enum<E> & CodeEnum> extends XmlAdapter<CodeEnumImpl,E> {

    public static <T extends Enum<T> & CodeEnum> T getFromName(Class<T> clazz, String name) {
        if (name == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (name.equals(t.name())) {
                return t;
            }
        }

        return null;
    }
    public static <T extends Enum<T> & CodeEnum> T getFromCode(Class<T> clazz, String code) {
        if (code == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (code.equals(t.getCode())) {
                return t;
            }
        }

        return null;
    }
    public static <T extends Enum<T> & CodeEnum> T getFromString(Class<T> clazz, String aString) {
        if (aString == null) return null;

        T[] values = clazz.getEnumConstants();

        for (T t : values) {
            if (aString.equals(t.getCode()) || aString.equals(t.name()) || aString.equals(t.getDescription())) {
                return t;
            }
        }

        return null;
    }

    @Override
    public E unmarshal(CodeEnumImpl value) throws Exception {
        if (value == null) return null;

        String valueString = value.getValue();
        if (valueString == null)
            valueString = value.getCode();
        if (valueString == null)
            valueString = value.getDescription();
        if (valueString == null)
            return null;

        Type generic = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return getFromString((Class<E>)generic, valueString);
    }

    @Override
    public CodeEnumImpl marshal(E value) throws Exception {
        return value == null ? null : new CodeEnumImpl(value);
    }
}
import org.apache.commons.lang3.StringUtils;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(CompanyCode.Adapter.class)
public enum CompanyCode implements CodeEnum {

    // Changed "Commmercial" to "Client" based on inputs from ...Greg, Tamil
    Client("CM", "Client"), Medicare("MC", "Medicare"), Medicaid("MD",
            "Medicaid"), Private("PI", "Private Ins"), Patient("PT", "Patient");

    private String code;
    private String description;

    private CompanyCode(String code, String label) {
        this.code = code;
        this.description = label;
    }

    public String getDescription() {
        return description;
    }

    public String getCode() {
        return code;
    }

    public static CompanyCode fromCode(String code) {
        if (StringUtils.isEmpty(code)) {
            return null;
        }

        for (CompanyCode freq : values()) {
            if (freq.getCode().equalsIgnoreCase(code)) {
                return freq;
            }
        }
        throw new IllegalArgumentException("Invalid CompanyCode code: " + code);
    }

    public String toString() {
        return description;
    }

    public static class Adapter extends CodeEnumXmlAdapter<CompanyCode> {}
}
import javax.xml.bind.annotation.XmlElement;

/**
 * Created by Jeffrey Hoffman on 6/24/2015.
 */
public class CodeEnumImpl  {
    String value;
    String description;
    String code;

    public CodeEnumImpl() {

    }
    public <E extends Enum<E> & CodeEnum> CodeEnumImpl(E value) {
        if (value != null) {
            this.value = value.name();
            this.description = value.getDescription();
            this.code = value.getCode();
        }
    }

    @XmlElement
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @XmlElement
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @XmlElement
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Override
    public String toString() {
        return value == null ? null : value.toString();
    }
}
异常描述:类[class]的对象[Private Ins] com.labcorp.phoenix.biz.enums.CompanyCode]无法转换为 [类java.lang.Object]。内部异常:异常 [EclipseLink-115](Eclipse持久性服务)- 2.5.0.v20130507-3faac2b):org.eclipse.persistence.exceptions.DescriptorException异常 说明:没有为属性[Private]提供转换值。 映射: org.eclipse.persistence.oxm.mappings.XMLDirectMapping[companyCode-->companyCode/text()] 描述符:XMLDescriptor(com.labcorp.phoenix.quality.Root--> [数据库表(根)]位于 org.eclipse.persistence.exceptions.ConversionException.couldNotBeConverted(ConversionException.java:87) 在 org.eclipse.persistence.internal.jaxb.XMLJavaTypeConverter.convertObjectValueToDataValue(XMLJavaTypeConverter.java:178) 在 org.eclipse.persistence.oxm.mappings.XMLDirectMapping.convertObjectValueToDataValue(XMLDirectMapping.java:511) 在 org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getFieldValue(XMLDirectMapping.java:330) 在 org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.MarshallSingleva