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?

Odpowiedzi:


204

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

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

To zadziała w 100%


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.


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 .


16

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

@XmlAccessorType(XmlAccessType.FIELD)

pracował jak cham


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()
    {
    }
}

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.


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


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.


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

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()

5

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


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.


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

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.


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.


1

ModeleREP#getTimeSeries()musi być z @Transientadnotacją. To by pomogł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


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!


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)


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 .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.