【问题标题】:How to tell JAXB to ignore the properties from the parent class如何告诉 JAXB 忽略来自父类的属性
【发布时间】:2012-03-06 07:43:15
【问题描述】:

我在使用 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(参见@XmlTransient on third-party or external super class)中创建package-info.java

@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 上测试,另外在类路径中使用 JAXB 2.2.4-1 运行时。

是功能还是错误?

【问题讨论】:

    标签: jaxb


    【解决方案1】:

    您只需将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);
        }
    
    }
    

    【讨论】:

    • 感谢您的回答。为什么@XmlTransient在这种情况下会有神奇的治疗效果?
    • @dma_k - @XmlTransient 处理超类,因为这告诉 JAXB 实现从继承层次结构中忽略它,并将属性视为属于子类:blog.bdoughan.com/2011/06/…跨度>
    • 我遇到了来自 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(comment); } 所以它的 API 是一样的。 JAXB 现在序列化 commentHolder 属性。正常吗?谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-12
    • 1970-01-01
    相关资源
    最近更新 更多