Jaxb, Class ma dwie właściwości o tej samej nazwie

121

w jaxb próbuję odczytać plik xml tylko kilka elementów w pliku xml jest interesujących, więc chciałbym pominąć wiele elementów

Zawartość xml

xml próbuję przeczytać

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

moja klasa

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

Kiedy próbuję odczytać plik XLM, otrzymuję

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

nie rozumiem tego błędu

edytuj: używam jaxb-impl-2.1.12

ok, teraz nie mam żadnego błędu, ale kiedy sprawdzam mój obiekt, timeSeries ma wartość null ...

więc może jaxb wydaje się mieć problem z flx?

redfox26
źródło

Odpowiedzi:

204

Ja też miałem taki problem i ustawiłem to.

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

To zadziała w 100%

user2067376
źródło
8
Miałem ten sam problem. I nawet to działa, gdy dodamy tylko @XmlAccessorType (XmlAccessType.FIELD)
Ram Dutt Shukla
2
I rozwiązać ten problem przez usunięcie z @XmlAccessorType(XmlAccessType.FIELD)adnotacji
Hans Wouters
Brzmi dziwnie, ale pozbyłem się również tego wyjątku, redukując parę adnotacji \ @XmlRootElement @XmlAccessorType (XmlAccessType.FIELD) tylko do \ @XmlRootElement
Alex InTechno
3
Napotkałem ten sam problem z klasami wewnętrznymi dla adnotacji JAXB. Umieszczenie @XmlAccessorType (XmlAccessType.FIELD) w klasach wewnętrznych zadziałało!
Shoaib Khan
Bardzo dziękuję. W połączeniu z Lombok bardzo pomocny
Michael Hegner
25

Nie określiłeś, jakiej wersji JAXB-IMPL używasz, ale kiedyś miałem ten sam problem (z jaxb-impl 2.0.5) i rozwiązałem go używając adnotacji na poziomie pobieracza zamiast używać go na poziomie elementu.

megathor
źródło
To prawda. Właśnie usunąłem adnotację z członka i umieściłem ją na poziomie ustawiacza i zadziałało.
Varun
22

Widziałem też podobne problemy, takie jak ten.

Myślę, że dzieje się tak z powodu miejsca, w którym używamy adnotacji@XMLElement ” w klasie (fasola).

I myślę, że JAXB (procesor adnotacji) traktuje pole członkowskie i metodę pobierania tego samego elementu pola jako różne właściwości, kiedy używamy adnotacji @XMLElement na poziomie pola i rzucamy wyjątek IllegalAnnotationExceptions .

Komunikat o wyjątku:

Klasa ma dwie właściwości o tej samej nazwie „timeSeries”

W metodzie Gettera:

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

W polu członka:

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

Rozwiązanie: Zamiast używać @XmlElement w polu , użyj go w metodzie pobierającej .

Sriram
źródło
16

właśnie dodałem to do mojej klasy

@XmlAccessorType(XmlAccessType.FIELD)

pracował jak cham

Ismael ozil
źródło
Działa również z adnotacją @Data firmy lombok.
digz6666
16

Istnieje wiele rozwiązań, ale zasadniczo, jeśli robisz adnotacje w deklaracji zmiennej, potrzebujesz @XmlAccessorType(XmlAccessType.FIELD) , ale jeśli wolisz adnotować metodę get lub set, to nie.

Możesz więc:

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

Lub:

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

    @XmlElement(name = "STATUS")         
    public int getStatus()
    {
    }
}
Pieczone Inhalf
źródło
Wspaniale. Dzięki :) +1
Anish B.
11

Twoje JAXB patrzy zarówno na getTimeSeries()metodę, jak i na członka timeSeries. Nie mówisz, której implementacji JAXB używasz, ani jej konfiguracji, ale wyjątek jest dość jasny.

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

i

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

Musisz skonfigurować swoje rzeczy JAXB, aby używały adnotacji (zgodnie z twoimi @XmlElement(name="TimeSeries")) i ignorowały metody publiczne.

ptomli
źródło
już to robię: @XmlElement (name = "TimeSeries") protected List <TimeSeries> timeSeries;
redfox 26
4
również zmieniam (XmlAccessType.FIELD) na (XmlAccessType.NONE), mogę utrzymać XmlElement na poziomie członka
redfox26
Musiałem też dodać @XmlTransient do zmiennej
HomeIsWhereThePcIs
8

Musisz skonfigurować klasę ModeleREPtak samo dobrze @XmlAccessorType(XmlAccessType.FIELD), jak w przypadku klasyTimeSeries .

Spójrz na OOXS

Mikrofon
źródło
8

Jeśli użyjemy poniższych adnotacji i usuniemy adnotację „@XmlElement”, kod powinien działać poprawnie, a wynikowy XML miałby nazwy elementów podobne do elementu członkowskiego klasy.

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

W przypadku, gdy użycie „@XmlElement” jest naprawdę wymagane, należy zdefiniować go jako poziom pola, a kod powinien działać idealnie. Nie definiuj adnotacji na górze metody pobierającej.

Wypróbowałem oba powyższe podejścia i udało mi się rozwiązać problem.

Naveen Rahangdale
źródło
7

„Klasa ma dwie właściwości o tej samej nazwie, wyjątek” może się zdarzyć, gdy masz członka klasy x z publicznym poziomem dostępu i funkcją pobierającą / ustawiającą dla tego samego członka.

Zgodnie z praktyczną zasadą Javy nie zaleca się używania publicznego poziomu dostępu razem z metodami pobierającymi i ustawiającymi.

Sprawdź to, aby uzyskać więcej informacji: Właściwość publiczna czy własność prywatna z funkcją getter?

Aby to naprawić:

  1. Zmień poziom dostępu swojego członka na prywatny i zachowaj swoją osobę pobierającą / ustawiającą
  2. Usuń getter i setter elementu członkowskiego
Naor Bar
źródło
6

To są dwie właściwości, na które patrzy JAXB.

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

i

protected java.util.List testjaxp.ModeleREP.timeSeries

Można tego uniknąć, używając adnotacji JAXB w metodzie get, tak jak wspomniano poniżej.

@XmlElement(name="TimeSeries"))  
public java.util.List testjaxp.ModeleREP.getTimeSeries()
Kondal Kolipaka
źródło
5

po prostu zadeklaruj zmienne składowe jako prywatne w klasie, którą chcesz przekonwertować na XML. Miłego kodowania

Tayab Hussain
źródło
To powinno być przyjęte rozwiązanie. Jeśli zadeklarujesz zmienną składową jako publiczną, JABX przeanalizuje ją oprócz metod z adnotacjami getter / setter i wypluje wyjątek. To świetny przykład, w którym projektanci biblioteki jabx poszli o krok dalej, próbując stworzyć elastyczność, i ostatecznie ułatwili nieprawidłowe konfiguracje. Sam rozwiązałem problem, zmieniając jednocześnie jeden wiersz kodu, śledząc wstecz do zmiennej składowej.
Vortex
4

Ten sam problem, z jakim miałem do czynienia, dodałem

@XmlRootElement(name="yourRootElementName")

@XmlAccessorType(XmlAccessType.FIELD)

a teraz działa.

Indygowiec
źródło
3

Będzie działać, gdy umieścisz adnotację przed pobierającymi i usuniesz ją z chronionych atrybutów:

protected String codingScheme;

@XmlAttribute(name = "codingScheme")
public String getCodingScheme() {
    return this.codingScheme;
}
Lilia
źródło
Ja też mam ten sam problem. Ja również zauważyłem, że kiedy adnotacja jest zaznaczona nad atrybutami, widzę to. Czy to oznacza, że ​​zawsze należy go umieszczać przed getterami?
Pavan Dittakavi
@Pavan Tak, myślę, że tak. W przeciwnym razie sprawia mi to te same problemy co ty
Lilia
2

Właśnie napotkałem ten problem i rozwiązałem go.

Źródłem problemu jest to, że masz zarówno XmlAccessType.FIELD, jak i pary metod pobierających i ustawiających. Rozwiązaniem jest usunięcie seterów i dodanie domyślnego konstruktora oraz konstruktora, który przyjmuje wszystkie pola.

Slava Imeshev
źródło
Miałem ten sam błąd, a adnotacja, o której wspomniałaś, rozwiązała go, dzięki!
gyorgyabraham
1

Miałem klasę usług z podpisem jak poniżej "

@WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {

W biegu mam ten sam błąd dla FetchIQAStatusResponseVOpól. Właśnie dodałem wiersz na FetchIQAStatusResponseVO:

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

i to rozwiązało problem.

S Agrawal
źródło
1

ModeleREP#getTimeSeries()musi być z @Transientadnotacją. To by pomogło.

Armer B.
źródło
0

Dodawanie adnotacji @XmlTransientrozwiązuje ten problem

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

Więcej informacji można znaleźć pod adresem http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html

kmaziarz
źródło
1
Myślę, że to bardziej hack niż rozwiązanie. To mówi jaxb, aby zignorował metodę, zamiast uświadamiać mu, że to to samo.
Hans Wouters
Hack czy nie to JEST najlepsze rozwiązanie, aby obejść coś, czego nie można opisać jako nic innego niż błąd, użyłem @XmlAccessorType (XmlAccessType.FIELD), który był w większości ignorowany, a dodanie @XmlTransient do każdej właściwości było jedynym sposobem na napraw ten problem. Dzięki!
Ralph Ritoch
0

Szybkim i prostym sposobem rozwiązania tego problemu jest usunięcie @XmlElement(name="TimeSeries")instrukcji deklaracji zmiennej protected List<TimeSeries> timeSeries;z góry na górę jej metody pobierającej,public List<TimeSeries> getTimeSeries() .

Twoja ModeleREPklasa będzie więc wyglądać następująco:

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

Mam nadzieję, że to pomoże!

Sourav Purakayastha
źródło
Wspomniałeś „Prosty sposób”. Ciekawe, czy jest jakieś inne wyjście z tego - a nie inna adnotacja, którą można by wykorzystać ?.
Pavan Dittakavi
0

Zrobiłem próbę i błąd i doszedłem do wniosku, że musisz użyć tylko jednego z nich @XMLElementlub @XmlAccessorType(XmlAccessType.FIELD).

Kiedy używać którego?

Przypadek 1 : Jeśli nazwy pól i nazwa elementu, którego chcesz użyć w pliku xml są różne, musisz użyć @XMLElement(name="elementName"). Ponieważ spowoduje to powiązanie pól z nazwą elementu i wyświetlenie ich w pliku XML.

Przypadek 2 : Jeśli nazwy pól i odpowiednia nazwa elementu w xml są takie same, możesz po prostu użyć@XmlAccessorType(XmlAccessType.FIELD)

Nilam Dhami
źródło
0

Podano wiele rozwiązań, a elementy wewnętrzne zostały krótko omówione przez @Sriram i @ptomli. Chcę tylko dodać kilka odniesień do kodu źródłowego, aby pomóc zrozumieć, co dzieje się pod maską.

Domyślnie (tj. Żadne dodatkowe adnotacje nie są używane w ogóle poza @XmlRootElementklasą główną), JABX próbuje organizować rzeczy ujawnione na dwa sposoby:

  1. pola publiczne
  2. metody pobierające, które są nazwane zgodnie z konwencją i mają odpowiednią metodę ustawiającą.

Zauważ, że jeśli pole jest (lub zwraca metodę) null, nie zostanie ono zapisane w wyniku.

Teraz, jeśli @XmlElementjest używany, rzeczy niepubliczne (mogą to być pola lub metody pobierające) mogą być również zorganizowane.

Ale te dwa sposoby, tj. Pola i metody pobierające, nie mogą ze sobą kolidować. W przeciwnym razie otrzymasz wyjątek .

wlnirvana
źródło