Jaxb, Class hat zwei gleichnamige Eigenschaften

120

Mit Jaxb versuche ich, eine XML-Datei zu lesen. Nur einige Elemente in der XML-Datei sind interessant. Daher möchte ich viele Elemente überspringen

XML-Inhalt

XML Ich versuche zu lesen

<?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>

meine Klasse

@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;
}
}

Wenn ich versuche, die XLM-Datei zu lesen, bekomme ich sie

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

Ich verstehe diesen Fehler nicht

edit: ich benutze jaxb-impl-2.1.12

Ok, jetzt habe ich keinen Fehler, aber wenn ich mein Objekt überprüfe, ist timeSeries null ...

Also scheint Jaxb vielleicht ein Problem mit FLX zu haben?

redfox26
quelle

Antworten:

204

Ich hatte auch ein solches Problem und habe es eingestellt.

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

Dies wird 100% funktionieren

user2067376
quelle
8
Ich hatte das gleiche Problem. Und selbst es funktioniert, wenn wir nur @XmlAccessorType (XmlAccessType.FIELD) hinzufügen
Ram Dutt Shukla
2
Ich habe das Problem gelöst, indem ich die @XmlAccessorType(XmlAccessType.FIELD)Anmerkung entfernt habe
Hans Wouters
Klingt seltsam, aber ich habe diese Ausnahme auch beseitigt, indem ich zwei Anmerkungen \ @XmlRootElement @XmlAccessorType (XmlAccessType.FIELD) auf nur \ @XmlRootElement
Alex InTechno
3
Ich bin auf dasselbe Problem mit Inner-Klassen für JAXB Annotation gestoßen. Das Platzieren von @XmlAccessorType (XmlAccessType.FIELD) in inneren Klassen hat funktioniert!
Shoaib Khan
Super, vielen Dank. In Kombination mit Lombok sehr hilfreich
Michael Hegner
25

Sie haben nicht angegeben, welche JAXB-IMPL-Version Sie verwenden, aber einmal hatte ich das gleiche Problem (mit jaxb-impl 2.0.5) und habe es mithilfe der Annotation auf Getter-Ebene gelöst, anstatt es auf Member-Ebene zu verwenden.

Megathor
quelle
Das ist richtig. Ich habe gerade die Anmerkung vom Mitglied entfernt und sie auf Setter-Ebene gesetzt, und es hat funktioniert.
Varun
22

Ich habe auch einige ähnliche Probleme wie dieses gesehen.

Ich denke, das liegt an der Stelle, an der wir die Annotation " @XMLElement " in der ( Bean- ) Klasse verwenden.

Und ich denke, der JAXB (Annotation Processor) betrachtet die Member Field & Getter-Methode desselben Feldelements als unterschiedliche Eigenschaften, wenn wir die Annotation @XMLElement auf Feldebene verwenden und die Ausnahme IllegalAnnotationExceptions auslösen .

Ausnahmemeldung:

Klasse hat zwei Eigenschaften des gleichen Namens „Zeitreihen“

Bei der Getter-Methode:

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

Im Mitgliederfeld:

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

Lösung: Verwenden Sie @XmlElement nicht im Feld , sondern in der Getter- Methode.

Sriram
quelle
16

habe dies gerade zu meiner Klasse hinzugefügt

@XmlAccessorType(XmlAccessType.FIELD)

arbeitete wie eine Cham

Ismael Ozil
quelle
Funktioniert auch mit der @ Data-Annotation von lombok.
digz6666
16

Es gibt mehrere Lösungen, aber grundsätzlich, wenn Sie die Variablendeklaration mit Anmerkungen versehen, benötigen Sie @XmlAccessorType(XmlAccessType.FIELD)diese. Wenn Sie jedoch lieber eine get- oder eine set-Methode mit Anmerkungen versehen möchten, ist dies nicht der Fall.

So können Sie tun:

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

Oder:

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

    @XmlElement(name = "STATUS")         
    public int getStatus()
    {
    }
}
In der Hälfte gebacken
quelle
Wunderbar. Danke :) +1
Anish B.
11

Ihr JAXB betrachtet sowohl die getTimeSeries()Methode als auch das Mitglied timeSeries. Sie sagen nicht, welche JAXB-Implementierung Sie verwenden oder welche Konfiguration sie haben, aber die Ausnahme ist ziemlich klar.

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

und

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

Sie müssen Ihr JAXB-Material so konfigurieren, dass Anmerkungen (gemäß Ihren Angaben @XmlElement(name="TimeSeries")) verwendet und öffentliche Methoden ignoriert werden.

ptomli
quelle
Ich mache bereits: @XmlElement (name = "TimeSeries") protected List <TimeSeries> timeSeries;
Redfox26
4
Auch ich ändere (XmlAccessType.FIELD) in (XmlAccessType.NONE), ich kann XmlElement auf der Mitgliederebene halten
redfox26
Ich musste auch @XmlTransient zur Variablen hinzufügen
HomeIsWhereThePcIs
8

Sie müssen die Klasse ModeleREPgenauso konfigurieren @XmlAccessorType(XmlAccessType.FIELD)wie mit der Klasse TimeSeries.

Schauen Sie sich auch OOXS an

Mike
quelle
8

Wenn wir die folgenden Annotationen verwenden und die Annotation "@XmlElement" entfernen, sollte der Code ordnungsgemäß funktionieren und das resultierende XML würde die Elementnamen ähnlich dem Klassenmitglied haben.

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

Falls die Verwendung von "@XmlElement" wirklich erforderlich ist, definieren Sie es bitte als Feldebene und der Code sollte perfekt funktionieren. Definieren Sie die Anmerkung nicht oben in der Getter-Methode.

Hatte beide oben genannten Ansätze ausprobiert und musste das Problem beheben.

Naveen Rahangdale
quelle
7

"Klasse hat zwei Eigenschaften mit derselben Namensausnahme" kann auftreten, wenn Sie ein Klassenmitglied x mit einer öffentlichen Zugriffsebene und einen Getter / Setter für dasselbe Mitglied haben.

Als Java-Faustregel wird nicht empfohlen, eine öffentliche Zugriffsebene zusammen mit Getter und Setter zu verwenden.

Überprüfen Sie dies für weitere Details: Öffentliches Eigentum VS Privateigentum mit Getter?

Um das zu beheben:

  1. Ändern Sie die Zugriffsebene Ihres Mitglieds auf privat und behalten Sie Ihren Getter / Setter
  2. Entfernen Sie den Getter und Setter des Mitglieds
Naor Bar
quelle
6

Dies sind die beiden Eigenschaften, die JAXB betrachtet.

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

und

protected java.util.List testjaxp.ModeleREP.timeSeries

Dies kann vermieden werden, indem die JAXB-Annotation at get-Methode wie unten erwähnt verwendet wird.

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

Deklarieren Sie einfach die Mitgliedsvariablen in der Klasse, die Sie in XML konvertieren möchten, als privat. Viel Spaß beim Codieren

Tayab Hussain
quelle
Dies sollte die akzeptierte Lösung sein. Wenn Sie Ihre Mitgliedsvariable als öffentlich deklarieren, analysiert JABX sie zusätzlich zu den mit Getter / Setter-Annotationen versehenen Methoden und spuckt die Ausnahme aus. Es ist ein großartiges Beispiel, bei dem Designer von Jabx-Bibliotheken einen Schritt weiter gegangen sind, um Flexibilität zu schaffen, und am Ende ungültige Konfigurationen ermöglicht haben. Ich habe das Problem selbst behoben, indem ich jeweils eine Codezeile geändert und auf die Mitgliedsvariable zurückgegriffen habe.
Vortex
3

Das gleiche Problem, mit dem ich konfrontiert war, fügte ich hinzu

@XmlRootElement(name="yourRootElementName")

@XmlAccessorType(XmlAccessType.FIELD)

und jetzt funktioniert es.

Anil
quelle
2

Ich bin gerade auf dieses Problem gestoßen und habe es gelöst.

Die Ursache des Problems ist, dass Sie sowohl XmlAccessType.FIELD als auch Paare von Gettern und Setzern haben. Die Lösung besteht darin, Setter zu entfernen und einen Standardkonstruktor und einen Konstruktor hinzuzufügen, der alle Felder akzeptiert.

Slava Imeshev
quelle
Ich hatte den gleichen Fehler und die von Ihnen erwähnte Anmerkung hat ihn behoben, danke!
Gyorgyabraham
2

Dies funktioniert, wenn Sie Ihre Anmerkung vor die Getter stellen und sie aus den geschützten Attributen entfernen:

protected String codingScheme;

@XmlAttribute(name = "codingScheme")
public String getCodingScheme() {
    return this.codingScheme;
}
Lilia
quelle
Auch ich habe das gleiche Problem. Ich habe auch beobachtet, dass ich dies sehe, wenn die Anmerkung über den Attributen markiert ist. Bedeutet dies, dass es immer vor den Gettern platziert werden sollte?
Pavan Dittakavi
@Pavan Ja ich denke schon. Ansonsten verursacht es mir die gleichen Probleme als Sie
Lilia
1

Ich hatte eine Serviceklasse mit der folgenden Unterschrift "

@WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {

Beim Ausführen habe ich den gleichen Fehler für FetchIQAStatusResponseVOFelder erhalten. Ich habe gerade eine Zeile hinzugefügt über FetchIQAStatusResponseVO:

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

und dies löste das Problem.

S Agrawal
quelle
1

ModeleREP#getTimeSeries()müssen mit @TransientAnmerkungen sein. Das würde helfen.

Armer B.
quelle
0

Das Kommentieren mit @XmlTransientbehebt dieses Problem

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

Weitere Informationen finden Sie unter http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html

kmaziarz
quelle
1
Ich denke, das ist eher ein Hack als eine Lösung. Dies weist jaxb an, die Methode zu ignorieren, anstatt sich bewusst zu machen, dass es dasselbe ist.
Hans Wouters
Hack oder nicht Dies ist die beste Lösung, um etwas zu umgehen, das nicht als Fehler beschrieben werden kann. Ich habe @XmlAccessorType (XmlAccessType.FIELD) verwendet, das größtenteils ignoriert wurde, und das Hinzufügen von @XmlTransient zu jeder Eigenschaft war der einzige Weg Beheben Sie dieses Problem. Vielen Dank!
Ralph Ritoch
0

Eine schnelle und einfache Möglichkeit, dieses Problem zu beheben, besteht darin, die @XmlElement(name="TimeSeries")Anweisung vom Anfang der Variablendeklaration protected List<TimeSeries> timeSeries;an den Anfang des Getters zu entfernen.public List<TimeSeries> getTimeSeries() .

So ModeleREPsieht Ihre Klasse aus:

@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;
  }
}

Ich hoffe es hilft!

Sourav Purakayastha
quelle
Sie erwähnen "Ein einfacher Weg". Neugierig, gibt es einen anderen Ausweg - keine andere Anmerkung, die genutzt werden könnte?
Pavan Dittakavi
0

Ich habe Versuch und Irrtum gemacht und bin zu dem Schluss gekommen, dass Sie nur eines von beiden @XMLElementoder verwenden müssen @XmlAccessorType(XmlAccessType.FIELD).

Wann welche verwenden?

Fall 1 : Wenn Ihre Feldnamen und Elementnamen, die Sie in einer XML-Datei verwenden möchten, unterschiedlich sind, müssen Sie diese verwenden @XMLElement(name="elementName"). Da dies Felder mit diesem Elementnamen bindet und in einer XML-Datei anzeigt.

Fall 2 : Wenn sowohl die Feldnamen als auch der jeweilige Elementname in XML identisch sind, können Sie einfach verwenden@XmlAccessorType(XmlAccessType.FIELD)

Nilam Dhami
quelle
0

Es wurden viele Lösungen angegeben, und die Interna werden auch von @Sriram und @ptomli kurz angesprochen. Ich möchte nur ein paar Verweise auf den Quellcode hinzufügen, um zu verstehen, was unter der Haube passiert.

Standardmäßig (dh es werden überhaupt keine zusätzlichen Anmerkungen verwendet, außer @XmlRootElementfür die Root-Klasse) versucht JABX, die auf zwei Arten offen gelegten Objekte zu marshallen:

  1. öffentliche Felder
  2. Getter-Methoden , die nach der Konvention benannt sind und eine entsprechende Setter-Methode haben.

Beachten Sie, dass wenn ein Feld ist (oder eine Methode zurückgibt) null , die zurückgegeben wird) nicht in die Ausgabe geschrieben wird.

Nun wenn @XmlElement es nun verwendet wird, können auch nicht öffentliche Dinge (Felder oder Getter-Methoden) gemarshallt werden.

Die beiden Methoden, dh Felder und Getter-Methoden, dürfen jedoch nicht miteinander in Konflikt stehen. Andernfalls erhalten Sie die Ausnahme .

wlnirvana
quelle