2012-04-13 102 views
3

想象我有这样的定义枚举: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() { .. } 
} 

默认莫西即​​将其序列化到JSON是这样的:

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

是否有配置莫西(映射文件)的方式序列化枚举像普通类:

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

什么是这样做的呢?您需要唯一标识枚举元素的_only_信息就是名称。 – 2012-04-13 16:14:15

+0

唯一的原因是保留返回JSON的API。我正在调查,看看我们是否可以使用MOXY来取代原生JSON串行器。 – Waldek 2012-04-13 19:00:47

回答

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

要指定莫西为您的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" 
    } 
} 

对于更多Informati在