且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

通过JAXB为枚举提供定制值序列化

更新时间:2023-09-27 09:34:34

尝试使用 XmlAdapter 机制。您为每个枚举类型创建一个 XmlAdapter 子类,并且知道如何将XML枚举/解组件。



  public class QualifierAdapter extends XmlAdapter< String,Qualifier> {

public String marshal(限定符限定符){
return qualifier.getCode();
}

public Qualifier unmarshal(String val){
return Qualifier.getFromCode(val); //我假设你有办法这样做
}
}

然后在模型类中:

  @XmlJavaTypeAdapter(QualifierAdapter.class)
私有限定符限定符;

您还可以在包级别,在名为包的文件中声明此-info.java 在与您的模型类相同的包中,使用相当特殊的包注释:

  @ javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters({
@ javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(
type = Qualifier.class,value = QualifierAdapter.class

})
package com.xyz;


For a project I'm working on, we have a lot of enums in use. The model object itself is composed from a lot of tiny classes; this model we then serialize to our DB as XML via JAXB. Now, we want to be able to serialize our enum values using the return of a particular method in the enum; that is given:

public enum Qualifier {
    FOO("1E", "Foo type document"),
    BAR("2", "Bar object");

    private String code, description;

    public Qualifier(String code, String description) {
        this.code = code;
        this.description = description;
    }

    public String getCode() {
        return this.code;
    }

    public String getDescription() {
        return this.description;
    }
}

etc. etc. Currently, when serialized to XML, we get something like:

<qualifier>FOO</qualifier>

which is how JAXB handles it. However, we need the value to be the return of getCode(), and a whole lot of our enums do follow that convention (with a corresponding static method for lookup via code), so that the above XML fragment looks like:

<qualifier>1E</qualifier>

instead. We can annotate it with @XmlEnum and @XmlEnumValue, but that's too tedious -- some enums have up to 30 enumerated values, and hand-editing it is not good. We're also thinking of using a custom serializer instead, but I'd like to avoid going that route for now (but if that's the way to go, then I have no problem with it).

Any ideas how?

Try using the XmlAdapter mechanism for this. You create an XmlAdapter subclass for each enum type, and which knows how to marshal/unmarshal the enum to and from XML.

You then associate the adapter with the property, e.g.

public class QualifierAdapter extends XmlAdapter<String, Qualifier> {

   public String marshal(Qualifier qualifier) {
      return qualifier.getCode();
   }

   public Qualifier unmarshal(String val) {
      return Qualifier.getFromCode(val);   // I assume you have a way of doing this
   }
}

and then in the model classes:

@XmlJavaTypeAdapter(QualifierAdapter.class)
private Qualifier qualifier;

You can also declare this at the package level, inside a file called package-info.java in the same package as your model classes, using the rather idiosyncratic package annotations:

@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters({
  @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(
    type=Qualifier.class, value=QualifierAdapter.class
  )
})
package com.xyz;