2012-02-14 50 views
4

我面临JAXB的以下问题:它看起来像JAXB正在分析从最深的子类到父类的属性,并且子属性具有优先级。我想改变这种行为。特别是:如何告诉JAXB忽略来自父类的属性

的子类:

package test.sub; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlTransient; 


@XmlAccessorType(XmlAccessType.NONE) 
public class BasicDocument { 

    private String comment; 

    public String getComment() { 
     return comment; 
    } 

    public void setComment(String cost) { 
     this.comment = cost; 
    } 
} 

的父类:

package test; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

import org.apache.commons.lang.builder.ToStringBuilder; 
import org.apache.commons.lang.builder.ToStringStyle; 

import test.sub.BasicDocument; 

@XmlRootElement(name="Description", namespace="http://www.w3.org/1999/02/22-rdf-syntax-ns#") 
@XmlAccessorType(XmlAccessType.PROPERTY) 
class Document extends BasicDocument { 

    private String identifier; 

    @XmlElement(name = "identifier", namespace = "http://purl.org/dc/terms/") 
    public String getIdentifier() { 
     return identifier; 
    } 

    public void setIdentifier(String identifier) { 
     this.identifier = identifier; 
    } 

    @Override 
    @XmlElement(name = "abstract", namespace = "http://purl.org/dc/terms/") 
    public String getComment() { 
     return super.getComment(); 
    } 

    @Override 
    public String toString() { 
     return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 
    } 
} 

编组站工作正常:

Document document = new Document(); 

document.setIdentifier("12A"); 
document.setComment("special"); 

StringWriter w = new StringWriter(); 

jaxbContext.createMarshaller().marshal(document, new StreamResult(w)); 

System.out.println(w); 

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:Description xmlns:ns2="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/dc/terms/"> 
    <abstract>special</abstract> 
    <identifier>12A</identifier> 
</ns2:Description> 

但是编组忽略这是在儿童BasicDocument类的属性(t.xml正是上面的XML):

JAXBContext jaxbContext = JAXBContext.newInstance(Document.class); 

Document document = (Document) jaxbContext.createUnmarshaller().unmarshal(Document.class.getResourceAsStream("t.xml")); 

System.out.println("out: " + document); 

输出:

out: Document[identifier=12A,comment=<null>] 

预期:

out: Document[identifier=12A,comment=special] 

基本上@XmlAccessorType(XmlAccessType.NONE)BasicDocument(见Ignore a parent class when Serializing to XML)没有效果。此外,在包装test.sub创建package-info.java(见@XmlTransient on third-party or external super class)是这样的:

@XmlAccessorType(XmlAccessType.NONE) 
package test.sub; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 

没有效果。只有@XmlTransient public class BasicDocument工作。理想情况下,我不想在孩子身上添加任何注释并仅通过package-info.java来控制此行为。我怎样才能做到这一点?

在JDK 1.6.0_27上测试,另外在classpath中使用JAXB 2.2.4-1运行库。

它是功能还是bug?

回答

2

您只需将setComment方法添加到Document类。没有它,即使该方法存在于父类中,它仍被视为只写属性。

public void setComment(String comment) { 
    super.setComment(comment); 
} 

全部来源为Document

package test; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

import org.apache.commons.lang.builder.ToStringBuilder; 
import org.apache.commons.lang.builder.ToStringStyle; 

import test.sub.BasicDocument; 

@XmlRootElement(name="Description", namespace="http://www.w3.org/1999/02/22-rdf-syntax-ns#") 
@XmlAccessorType(XmlAccessType.PROPERTY) 
class Document extends BasicDocument { 

    private String identifier; 

    @XmlElement(name = "identifier", namespace = "http://purl.org/dc/terms/") 
    public String getIdentifier() { 
     return identifier; 
    } 

    public void setIdentifier(String identifier) { 
     this.identifier = identifier; 
    } 

    @Override 
    @XmlElement(name = "abstract", namespace = "http://purl.org/dc/terms/") 
    public String getComment() { 
     return super.getComment(); 
    } 

    public void setComment(String comment) { 
     super.setComment(comment); 
    } 

    @Override 
    public String toString() { 
     return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); 
    } 

} 
+0

感谢您的回答。为什么'@ XmlTransient'在这种情况下具有魔法治疗效果? – 2012-02-15 22:31:03

+1

@dma_k - '@ XmlTransient'在超类上工作,因为它告诉JAXB实现从继承层次结构中忽略它,并将属性视为属于子类:http://blog.bdoughan.com/2011 /06/ignoring-inheritance-with-xmltransient.html – 2012-02-16 15:57:24

+0

我面对JAXB的一种“有趣的行为”。我在'BasicDocument'中引入了一个中间类'CommentHolder',它包含'String comment'属性。 ''BasicDocument'增加了'CommentHolder getCommentHolder()'和'setCommentHolder(CommentHolder commentHolder)'代替get/setComment。 'Document'类更新如下:String getComment(){return super.getCommentHolder()。getComment(); }'和'void setComment(String comment){super.getCommentHolder()。setComment(评语); }'所以它的API是一样的。 JAXB现在序列化'commentHolder'属性。这是正常的吗?谢谢 – 2012-02-28 11:14:14