JAXB / MOXy能否以与常规类(非枚举)相同的方式序列化枚举?

时间:2012-04-13 16:12:36

标签: jaxb moxy

想象一下,我的枚举定义如下:

public enum ArchiveStatus implements Serializable {
  CANDIDATE         (0, "CANDIDATE", "Candidate for archival"),
  IN_LIBRARY          (1, "IN-LIBRARY", ".."),
  FROM_LIBRARY        (2, "FROM-LIBRARY", "..");

  private int id;
  private String shortName;
  private String longName;

  public ArchiveStatus( int id, String shortName, String longName ) {
    ..
  }

  public int getId() { .. }
  public String getShortName() { .. }
  public String getLongName() { .. }
}

默认情况下,MOXy会将其序列化为JSON,如下所示:

{
   ..
   "archiveStatus": "CANDIDATE",
   ..
}

有没有办法配置MOXy(在映射文件中)像常规类一样序列化枚举:

{
   ..
   "archiveStatus": { "id" : 0, "shortName": "CANDIDATE", "longName": "Candidate for archival" },
   ..
}

1 个答案:

答案 0 :(得分:4)

注意:我是EclipseLink JAXB (MOXy)主管,是JAXB 2 (JSR-222)专家组的成员。

<强> ArchiveStatusAdapter

您可以通过利用XmlAdapter来解决此用例。 XmlAdapter是一种JAXB机制,允许您将一种类型的对象编组为另一种。

package forum10144489;

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

public class ArchiveStatusAdapter extends XmlAdapter<ArchiveStatusAdapter.AdaptedArchiveStatus, ArchiveStatus> {

    public static class AdaptedArchiveStatus {
        public int id;
        public String shortName;
        public String longName;
    }

    @Override
    public ArchiveStatus unmarshal(AdaptedArchiveStatus adaptedArchiveStatus) throws Exception {
        if(null == adaptedArchiveStatus) {
            return null;
        }
        return ArchiveStatus.valueOf(adaptedArchiveStatus.shortName);
    }

    @Override
    public AdaptedArchiveStatus marshal(ArchiveStatus archiveStatus) throws Exception {
        if(null == archiveStatus) {
            return null;
        }
        AdaptedArchiveStatus adaptedArchiveStatus = new AdaptedArchiveStatus();
        adaptedArchiveStatus.id = archiveStatus.getId();
        adaptedArchiveStatus.longName = archiveStatus.getLongName();
        adaptedArchiveStatus.shortName = archiveStatus.getShortName();
        return adaptedArchiveStatus;
    }

}

<强>根

可以使用XmlAdapter注释在字段,属性,类型或包级别指定@XmlJavaTypeAdapter

package forum10144489;

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

public class Root {

    private ArchiveStatus archiveStatus;

    @XmlJavaTypeAdapter(ArchiveStatusAdapter.class)
    public ArchiveStatus getArchiveStatus() {
        return archiveStatus;
    }

    public void setArchiveStatus(ArchiveStatus archiveStatus) {
        this.archiveStatus = archiveStatus;
    }

}

<强> jaxb.properties

要将MOXy指定为JAXB提供程序,您需要在与域类相同的程序包中添加名为jaxb.properties的文件,并使用以下条目。

javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory

<强>演示

package forum10144489;

import java.io.StringReader;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(2);
        properties.put("eclipselink.media-type", "application/json");
        properties.put("eclipselink.json.include-root", false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Root.class}, properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StringReader jsonStringReader = new StringReader("{\"archiveStatus\" : {\"id\" : 0, \"shortName\" : \"CANDIDATE\", \"longName\" : \"Candidate for archival\"}}");
        StreamSource jsonSource = new StreamSource(jsonStringReader);
        Root root = unmarshaller.unmarshal(jsonSource, Root.class).getValue();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

<强>输出

以下是运行演示代码的输出:

{
   "archiveStatus" : {
      "id" : 0,
      "shortName" : "CANDIDATE",
      "longName" : "Candidate for archival"
   }
}

了解更多信息