java - JAXB注释问题

标签 java xml jaxb

我需要一些有关 JAXB 注释的帮助。我有一个 XML,我想将其作为 java 对象获取。 如果我按原样运行它,我将收到有关同名属性的错误(见下文)。当我注释掉功能和场景类中列表的 setter 时,错误将会消失,但我将需要这些 setter ...

错误:

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
Class has two properties of the same name "scenarioList"
    this problem is related to the following location:
        at public java.util.ArrayList generator.model.Feature.getScenarioList()
        at generator.model.Feature
        at private java.util.ArrayList generator.model.Features.featureList
        at generator.model.Features
    this problem is related to the following location:
        at private java.util.ArrayList generator.model.Feature.scenarioList
        at generator.model.Feature
        at private java.util.ArrayList generator.model.Features.featureList
        at generator.model.Features
Class has two properties of the same name "stepList"
    this problem is related to the following location:
        at public java.util.ArrayList generator.model.Scenario.getStepList()
        at generator.model.Scenario
        at private java.util.ArrayList generator.model.Feature.scenarioList
        at generator.model.Feature
        at private java.util.ArrayList generator.model.Features.featureList
        at generator.model.Features
    this problem is related to the following location:
        at private java.util.ArrayList generator.model.Scenario.stepList
        at generator.model.Scenario
        at private java.util.ArrayList generator.model.Feature.scenarioList
        at generator.model.Feature
        at private java.util.ArrayList generator.model.Features.featureList
        at generator.model.Features

要解析的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<features>
    <feature id="1">
        <name>Feature name 1</name>
        <description>Feature description 1</description>
        <scenarios>
            <scenario id="1">
                <name>Scenario name 1</name>
                <steps>
                    <step id="1"></step>
                    <step id="2"></step>
                </steps>
            </scenario>
            <scenario id="2">
                <name>Scenario name 2</name>
                <steps>
                    <step id="1"></step>
                    <step id="2"></step>
                </steps>
            </scenario>
        </scenarios>
    </feature>
    <feature id="2">
        <name>Feature name 2</name>
        <description>Feature description 2</description>
        <scenarios>
            <scenario id="4">
                <name>Scenario name 1</name>
                <steps>
                    <step id="1"></step>
                </steps>
            </scenario>
        </scenarios>
    </feature>
</features>

以下是模型类:

Features.java

package generator.model;

import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;  

@XmlRootElement(name = "features")
public class Features {

    @XmlElement(name = "feature")
    private ArrayList<Feature> featureList = null;

    public void setFeaturesList(ArrayList<Feature> featureList) {
        this.featureList = featureList;
    }

    public ArrayList<Feature> getFeatureList() {
        return featureList;
    }
}

Feature.java

package generator.model;

import java.util.ArrayList;
import javax.xml.bind.annotation.XmlAttribute;  
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;  

@XmlRootElement(name = "feature")
public class Feature {  

    @XmlElementWrapper(name = "scenarios")
    @XmlElement(name= "scenario")
    private ArrayList<Scenario> scenarioList = null;

    private int id;
    private String name;
    private String description;

    @XmlAttribute
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    } 

    @XmlElement
    public String getName() {  
        return name;  
    }

    public void setName(String name) {  
        this.name = name;  
    }  

    @XmlElement
    public String getDescription() {  
        return description;  
    }  

    public void setDescription(String description) {  
        this.description = description;  
    }


    public ArrayList<Scenario> getScenarioList() {
        return scenarioList;
    }

    public void setScenarioList(ArrayList<Scenario> scenarioList) {
        this.scenarioList = scenarioList;
    }

}  

场景.java

package generator.model;

import java.util.ArrayList;

import javax.xml.bind.annotation.XmlAttribute;  
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;  

@XmlRootElement(name = "scenario")
public class Scenario {  

    @XmlElementWrapper(name = "steps")
    @XmlElement(name= "step")
    private ArrayList<Step> stepList = null;

    private int id;
    private String name;

    @XmlAttribute
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    } 

    @XmlElement
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }

    public ArrayList<Step> getStepList() {
        return stepList;
    }

    public void setStepList(ArrayList<Step> stepList) {
        this.stepList = stepList;
    }  

}  

Step.java

package generator.model;

import javax.xml.bind.annotation.XmlAttribute;  
import javax.xml.bind.annotation.XmlRootElement;  

@XmlRootElement(name = "step")
public class Step {  

    private int id;

    @XmlAttribute
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    } 

}  

最佳答案

JAXB 自动映射字段或属性。如果@XmlAccessorType不存在,则默认为XmlAccessType.PUBLIC_MEMBER ,这意味着 ( see javadoc )

Every public getter/setter pair and every public field will be automatically bound to XML, unless annotated by XmlTransient.

就您而言,默认情况下,所有 public即使不存在注释,getter/setter 也会被映射。字段未映射,因为它们是 private ,除非明确注释。

因此,与 stepList 存在冲突和scenarioList映射两次:public getter/setter,因为 @XmlAccessorType不存在,并且该字段不存在,因为它已被注释。

请注意,在您的 Features 类中,您将有一个 <feature>元素(带注释的私有(private) featureList 字段)和 <featureList>元素(featureList 的公共(public) getter),两者具有相同的内容。

您可以通过添加@XmlTransient来避免它。对属性 getter 进行注释以避免自动映射。但我建议选择映射字段或属性,并相应地指定 @XmlAccessorType。

例如,您的 Scenario.java 可以映射为:

// Non static, non transient fields will be automatically be mapped unless annotated with XmlTransient.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "scenario")
public class Scenario {  

    @XmlElementWrapper(name = "steps")
    @XmlElement(name= "step")
    private ArrayList<Step> stepList = null;

    @XmlAttribute
    private int id;

    // Mapping a field to an element is the default, so this annotation is not strictly
    // needed, unless you want to change the default element name
    @XmlElement
    private String name;

    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    } 

    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }

    public ArrayList<Step> getStepList() {
        return stepList;
    }

    public void setStepList(ArrayList<Step> stepList) {
        this.stepList = stepList;
    }  

}  

关于java - JAXB注释问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61173308/

相关文章:

Java - 二进制标志 vector

java - Spring Websocket getServerName 服务中

java - 尝试使用自定义适配器填充 ListView

java - 如何播放很多音效?

jquery - 使用 jquery 将 XML 属性转为 HTML 选择值

python - NLTK 的 XMLCorpusReader 可以用于多文件语料库吗?

java - 从 ant 调用 wsimport 生成的类中去掉 JAXBElement

c# - Linq 查询 XML 以选择子节点的多个元素

java - 将对象编码为 xml 并删除 xmlns

java - 如果属性等于 xxx,JAXB 获取元素