Jaxb,Class具有两个相同名称的属性


120

使用jaxb,我尝试读取xml文件,而xml文件中只有几个元素很有趣,所以我想跳过许多元素

xml内容

我尝试读取的XML

<?xml version="1.0" encoding="UTF-8"?>
<!--Sample XML file generated by XMLSpy v2010 rel. 3 sp1 (http://www.altova.com)-->
<flx:ModeleREP xsi:schemaLocation="urn:test:mod_rep.xsd mod_rep.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flx="urn:test:mod_rep.xsd">
<flx:DocumentHeader>
    <flx:Identification v="04489"/>
</flx:DocumentHeader>
<flx:TimeSeries>
    <flx:Identification v="test1a"/>
    <flx:BusinessType v="A01"/>
    <flx:Product v="123a"/>
    <flx:ResourceObject codingScheme="N" v="testa"/>
    <flx:Period>
        <flx:TimeInterval v="2011-07-02T00:00/2011-07-16T00:00"/>
        <flx:Resolution v="PT2H"/>
        <flx:Pt>
            <flx:P v="1"/>
            <flx:Q unitCode="String" v="1.0"/>
            <flx:A currencyIdentifier="String" v="195.0"/>
        </flx:Pt>
    </flx:Period>
</flx:TimeSeries>
<flx:TimeSeries>
    <flx:Identification v="test2a"/>
    <flx:BusinessType v="A01"/>
    <flx:Product v="a123b"/>
    <flx:ResourceObject codingScheme="N" v="test2"/>
    <flx:Period>
        <flx:TimeInterval v="2011-07-02T00:00/2011-07-16T00:00"/>
        <flx:Resolution v="PT2H"/>
        <flx:Pt>
            <flx:P v="1"/>
            <flx:Q unitCode="String" v="1.0"/>
            <flx:A currencyIdentifier="String" v="195.0"/>
        </flx:Pt>
        <flx:Pt>
            <flx:P v="2"/>
            <flx:Q unitCode="String" v="1.0"/>
            <flx:A currencyIdentifier="String" v="195.0"/>
        </flx:Pt>
    </flx:Period>
</flx:TimeSeries>
</flx:ModeleREP>

我的课

@XmlRootElement(name="ModeleREP", namespace="urn:test:mod_rep.xsd")
public class ModeleREP {

  @XmlElement(name="TimeSeries")
  protected List<TimeSeries> timeSeries;

  public List<TimeSeries> getTimeSeries() {
  if (this.timeSeries == null) {
      this.timeSeries = new ArrayList<TimeSeries>();
  }
  return this.timeSeries;
  }

  public void setTimeSeries(List<TimeSeries> timeSeries) {
  this.timeSeries = timeSeries;
  }

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "TimeSeries")
public class TimeSeries {

@XmlElement(name="ResourceObject")
protected RessourceObject resourceObject;

@XmlElement(name = "Period")
protected Period period;

public RessourceObject getResourceObject() {
    return this.resourceObject;
}

public void setResourceObject(RessourceObject resourceObject) {
    this.resourceObject = resourceObject;
}

public Period getPeriod() {
    return this.period;
}

public void setPeriod(Period period) {
    this.period = period;
}

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ResourceObject")

public class RessourceObject {
@XmlAttribute(name = "codingScheme")
protected String codingScheme;

@XmlAttribute(name = "v")
protected String v;

public String getCodingScheme() {
    return this.codingScheme;
}

public void setCodingScheme(String codingScheme) {
    this.codingScheme = codingScheme;
}

public String getV() {
    return this.v;
}

public void setV(String v) {
    this.v = v;
}
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "Period")
public class Period {

@XmlElement(name = "TimeInterval")
protected TimeInterval timeInterval;

@XmlElement(name = "Pt")
protected List<Pt> pt;

public TimeInterval getTimeInterval() {
    return this.timeInterval;
}

public void setTimeInterval(TimeInterval timeInterval) {
    this.timeInterval = timeInterval;
}

public List<Pt> getPt() {
    if (this.pt == null) {
    this.pt = new ArrayList<Pt>();
    }
    return this.pt;
}

public void setPt(List<Pt> pt) {
    this.pt=pt;
}

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "TimeInterval")
public class TimeInterval {

@XmlAttribute(name = "v")
private String timeIntervalPeriod;

public String getTimeIntervalPeriod() {
    return this.timeIntervalPeriod;
}

public void setTimeIntervalPeriod(String timeIntervalPeriod) {
    this.timeIntervalPeriod = timeIntervalPeriod;
}

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Pt")
public class Pt {

@XmlElement(name = "P")
protected P p;

@XmlElement(name = "A")
protected A a;

public P getP() {
    return this.p;
}

public void setP(P p) {
    this.p = p;
}

public A getA() {
    return this.a;
}

public void setA(A a) {
    this.a = a;
}
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "P")
public class P {
@XmlAttribute(name = "v")
protected String position;


public String getPosition(){
    return this.position;
}

public void setPosition(String position){
    this.position=position;
}
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "A")
public class A {
@XmlAttribute(name = "v")
protected String calculatedAmount;

public String getCalculatedAmount() {
    return this.calculatedAmount;
}

public void setCalculatedAmount(String calculatedAmount) {
    this.calculatedAmount = calculatedAmount;
}
}

当我尝试读取xlm文件时,我得到了

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "timeSeries"
    this problem is related to the following location:
        at public java.util.List testjaxp.ModeleREP.getTimeSeries()
        at testjaxp.ModeleREP
    this problem is related to the following location:
        at protected java.util.List testjaxp.ModeleREP.timeSeries
        at testjaxp.ModeleREP

我不明白这个错误

编辑:我使用jaxb-impl-2.1.12

好的,现在我没有任何错误,但是当我检查对象时,timeSeries为null ...

所以也许jaxb似乎对flx有问题?

Answers:


204

我也遇到这样的问题,我设置了这个。

@XmlRootElement(name="yourRootElementName")
@XmlAccessorType(XmlAccessType.FIELD)

这将工作100%


8
我遇到过同样的问题。甚至当我们仅添加@XmlAccessorType(XmlAccessType.FIELD)时,它也能正常工作
Ram Dutt Shukla

2
我解决了这个问题,通过去除@XmlAccessorType(XmlAccessType.FIELD)注释
汉斯·沃特斯

听起来很奇怪,但我也通过将一对注释\ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD)减少为仅\ @XmlRootElement来摆脱了这个异常
Alex InTechno

3
使用JAXB Annotation的内部类遇到相同的问题。将@XmlAccessorType(XmlAccessType.FIELD)放在内部类上起作用!
Shoaib Khan

太好了,非常感谢。与龙目岛结合非常有帮助
Michael Hegner

25

您没有指定要使用的JAXB-IMPL版本,但是一旦遇到相同的问题(使用jaxb-impl 2.0.5),并在getter级别使用注释而不是在成员级别使用注释解决了它。


没错,我只是从成员中删除了注释,然后将其放在setter级别上就可以了。
Varun

22

我也看到过类似的问题。

我认为,这是因为的地方,我们用“ @XmlElement的注释中(豆)类。

我想,JAXB(注释处理器)认为相同的字段元素作为不同性质的成员字段&吸气剂的方法,当我们使用 @XmlElement注释在字段级别并抛出IllegalAnnotationExceptions异常。

异常消息:

类有两个属性的的相同 名称 “时间序列”

在吸气方法:

    at public java.util.List testjaxp.ModeleREP.getTimeSeries()

在会员领域:

    at protected java.util.List testjaxp.ModeleREP.timeSeries

解决方案: 不要在字段中使用@XmlElement,而应在getter方法中使用它。



16

有多种解决方案,但是从根本上讲,如果您对变量声明进行注释,则需要@XmlAccessorType(XmlAccessType.FIELD),但是,如果您希望对get方法或set方法进行注释,则不需要。

因此,您可以执行以下操作:

@XmlRootElement(name="MY_CLASS_A")
@XmlAccessorType(XmlAccessType.FIELD)
public class MyClassA
{
    @XmlElement(name = "STATUS")   
    private int status;
   //.. and so on
}

要么:

@XmlRootElement(name="MY_CLASS_A")
public class MyClassA
{
    private int status;

    @XmlElement(name = "STATUS")         
    public int getStatus()
    {
    }
}

精彩。谢谢:) +1
阿尼什·B

11

您的JAXB正在查看getTimeSeries()方法和成员timeSeries。您没有说您正在使用哪个JAXB实现或其配置,但是非常明显的例外。

在公共java.util.List上testjaxp.ModeleREP.getTimeSeries()

在受保护的java.util.List处testjaxp.ModeleREP.timeSeries

您需要配置JAXB内容以使用注释(根据您的说明@XmlElement(name="TimeSeries"))并忽略公共方法。


我已经做过:@XmlElement(name =“ TimeSeries”)受保护的List <TimeSeries> timeSeries;
redfox26 2011年

4
我也将(XmlAccessType.FIELD)更改为(XmlAccessType.NONE),我可以将XmlElement保留在成员级别
redfox26

我还需要将@XmlTransient添加到变量
HomeIsWhereThePcIs

8

您需要ModeleREP像配置class 一样配置@XmlAccessorType(XmlAccessType.FIELD)class TimeSeries

看看OOXS


8

如果我们使用以下注释并删除“ @XmlElement”注释,则代码应能正常工作,并且生成的XML具有与类成员相似的元素名称。

@XmlRootElement(name="<RootElementName>")
@XmlAccessorType(XmlAccessType.FIELD)

如果确实需要使用“ @XmlElement”,请定义它为字段级别,并且代码应该可以正常工作。不要在getter方法的顶部定义注释。

尝试了上述两种方法并解决了该问题。


7

当您有一个具有公共访问级别的类成员x和同一成员的getter / setter方法时,可能会发生 “类具有相同名称异常的两个属性”

作为Java的经验法则,不建议使用public访问级别与getter和setter一起使用。

检查更多详细信息: 公共财产VS带有吸气剂的私有财产?

要解决此问题:

  1. 将会员的访问权限级别更改为私有,并保持获取者/设置者的身份
  2. 删除成员的getter和setter

6

这是JAXB正在查看的两个属性。

public java.util.List testjaxp.ModeleREP.getTimeSeries()  

protected java.util.List testjaxp.ModeleREP.timeSeries

可以通过在get方法中使用JAXB注释来避免这种情况,如下所述。

@XmlElement(name="TimeSeries"))  
public java.util.List testjaxp.ModeleREP.getTimeSeries()

5

只需在要转换为XML的类中将成员变量声明为private即可。快乐编码


这应该是公认的解决方案。如果将成员变量声明为public,则JABX会解析它,除了使用getter / setter注释的方法外,还会吐出异常。这是一个很好的例子,jabx库设计人员在思考上花了更多的精力来尝试创建灵活性并最终促进了无效的配置。我通过一次更改一行代码来追溯到成员变量,从而自行解决了该问题。
Vortex

4

我添加了同样的问题

@XmlRootElement(name="yourRootElementName")

@XmlAccessorType(XmlAccessType.FIELD)

现在它正在工作。


3

当您将注释放在吸气剂之前,并将其从受保护的属性中删除时,它将起作用:

protected String codingScheme;

@XmlAttribute(name = "codingScheme")
public String getCodingScheme() {
    return this.codingScheme;
}

我也遇到了同样的问题。我也观察到,当在属性上标记注释时,我会看到这一点。这是否意味着总是将其放置在吸气剂之前?
Pavan Dittakavi

@Pavan是的,我是这样认为的。否则,它会给我带来与您相同的问题
Lilia

2

我刚遇到这个问题并解决了。

问题的根源是您同时拥有XmlAccessType.FIELD以及成对的getter和setter。解决方案是删除setter,并添加默认构造函数和采用所有字段的构造函数。


我遇到了同样的错误,您提到的注释解决了它,谢谢!
gyorgyabraham 2013年

1

我有一个带有以下签名的服务类”

@WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {

在运行时,我在FetchIQAStatusResponseVO字段上遇到了相同的错误。我刚刚在上添加了一行FetchIQAStatusResponseVO

@XmlAccessorType(XmlAccessType.FIELD) //This line added
public class FetchIQAStatusResponseVO {

这样就解决了问题。


1

ModeleREP#getTimeSeries()必须带有@Transient注释。那会有所帮助。


0

注释@XmlTransient可解决该问题

@XmlTransient
public void setTimeSeries(List<TimeSeries> timeSeries) {
   this.timeSeries = timeSeries;
}

请查看http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html了解更多详细信息


1
我认为这更多的是hack,而不是解决方案。这告诉jaxb忽略该方法,而不是使其意识到这是同一件事。
汉斯·沃特斯

不管是否破解,这都是解决某些无法描述的错误的最佳解决方案,我使用了@XmlAccessorType(XmlAccessType.FIELD),该方法通常被忽略,并且向每个属性添加@XmlTransient是唯一的方法修复此问题。谢谢!
拉尔夫·里托奇

0

解决此问题的快速简便方法是@XmlElement(name="TimeSeries")将变量声明语句顶部的删除protected List<TimeSeries> timeSeries;到其getter的顶部public List<TimeSeries> getTimeSeries()

因此,您的ModeleREP课程将类似于:

@XmlRootElement(name="ModeleREP", namespace="urn:test:mod_rep.xsd")
public class ModeleREP {


  protected List<TimeSeries> timeSeries;

  @XmlElement(name="TimeSeries")
  public List<TimeSeries> getTimeSeries() {
    if (this.timeSeries == null) {
      this.timeSeries = new ArrayList<TimeSeries>();
    }
    return this.timeSeries;
  }

  public void setTimeSeries(List<TimeSeries> timeSeries) {
    this.timeSeries = timeSeries;
  }
}

希望能帮助到你!


您提到“一种简单的方法”。很好奇,还有其他方法可以解决-是否可以利用其他注释?
Pavan Dittakavi

0

经过反复试验,得出的结论是,您只需使用@XMLElement或即可@XmlAccessorType(XmlAccessType.FIELD)

什么时候使用哪个?

情况1:如果要在xml文件中使用的字段名称和元素名称不同,则必须使用@XMLElement(name="elementName")。因为这将绑定具有该元素名称的字段并显示在XML文件中。

情况2:如果xml中的字段名称和相应的元素名称都相同,则可以简单地使用@XmlAccessorType(XmlAccessType.FIELD)


0

已经给出了许多解决方案,并且@Sriram和@ptomli也短暂地触及了内部。我只想添加一些对源代码的引用,以帮助了解幕后情况。

默认情况下(即,除了@XmlRootElement在根类上根本不使用任何额外的注释),JABX试图封送通过两种方式公开的内容:

  1. 公共领域
  2. getter方法的命名遵循约定,并有相应的setter方法。

请注意,如果字段为(或方法返回)null,则不会将其写入输出。

现在,如果@XmlElement使用了非公共事物(可以是字段或getter方法),也可以将其编组。

但是,字段和获取方法这两种方式一定不能相互冲突。否则,您将获得例外

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.