Jaxb, Class a deux propriétés du même nom


120

avec jaxb, j'essaie de lire un fichier xml, seuls quelques éléments du fichier xml sont intéressants, je voudrais donc sauter de nombreux éléments

contenu xml

xml j'essaye de lire

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

Ma classe

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

quand j'essaye de lire le fichier xlm je reçois je reçois

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

je ne comprends pas cette erreur

edit: j'utilise jaxb-impl-2.1.12

ok maintenant je n'ai aucune erreur, mais quand je vérifie mon objet, timeSeries est nul ...

alors peut-être que jaxb semble avoir un problème avec flx?

Réponses:


204

J'ai également rencontré un problème comme celui-ci et je l'ai défini.

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

Cela fonctionnera à 100%


8
J'ai eu le même problème. Et même cela fonctionne lorsque nous ajoutons uniquement @XmlAccessorType (XmlAccessType.FIELD)
Ram Dutt Shukla

2
J'ai résolu le problème en supprimant l' @XmlAccessorType(XmlAccessType.FIELD)annotation
Hans Wouters

Cela semble étrange, mais je me suis également débarrassé de cette exception en réduisant la paire d'annotations \ @XmlRootElement @XmlAccessorType (XmlAccessType.FIELD) à seulement \ @XmlRootElement
Alex InTechno

3
Ran dans le même problème avec les classes internes pour l'annotation JAXB. Placer @XmlAccessorType (XmlAccessType.FIELD) sur les classes internes a fonctionné!
Shoaib Khan

Génial, merci beaucoup. En combinaison avec Lombok très utile
Michael Hegner

25

Vous n'avez pas spécifié la version de JAXB-IMPL que vous utilisez, mais une fois j'ai eu le même problème (avec jaxb-impl 2.0.5) et je l'ai résolu en utilisant l'annotation au niveau du getter au lieu de l'utiliser au niveau du membre.


C'est correct, je viens de supprimer l'annotation du membre et de la mettre au niveau du setter et cela a fonctionné.
Varun

22

J'ai également vu des problèmes similaires comme celui-ci.

Je pense que c'est à cause de l' endroit où nous utilisons l' annotation " @XMLElement " dans la classe (bean).

Et je pense que le JAXB (processeur d'annotations) considère le champ membre et la méthode getter du même élément de champ comme des propriétés différentes, lorsque nous utilisons l' annotation @XMLElement au niveau du champ et lançons l' exception IllegalAnnotationExceptions .

Message d'exception:

La classe a deux propriétés du même nom "timeSeries"

À la méthode Getter:

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

Au champ membre:

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

Solution: au lieu d'utiliser @XmlElement dans le champ , utilisez-le dans la méthode getter .


16

vient de l'ajouter à ma classe

@XmlAccessorType(XmlAccessType.FIELD)

a travaillé comme un cham


Fonctionne également avec l'annotation @Data de lombok.
digz6666

16

Il existe plusieurs solutions, mais fondamentalement, si vous annotez sur la déclaration de variable, vous en avez besoin @XmlAccessorType(XmlAccessType.FIELD), mais si vous préférez annoter une méthode get ou set, vous ne le faites pas.

Vous pouvez donc faire:

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

Ou:

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

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

Merveilleux. Merci :) +1
Anish B.

11

Votre JAXB examine à la fois la getTimeSeries()méthode et le membre timeSeries. Vous ne dites pas quelle implémentation JAXB vous utilisez, ni sa configuration, mais l'exception est assez claire.

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

et

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

Vous devez configurer vos éléments JAXB pour utiliser des annotations (selon votre @XmlElement(name="TimeSeries")) et ignorer les méthodes publiques.


je fais déjà: @XmlElement (name = "TimeSeries") protected List <TimeSeries> timeSeries;
redfox26

4
aussi je change (XmlAccessType.FIELD) en (XmlAccessType.NONE), je peux garder XmlElement au niveau du membre
redfox26

J'avais également besoin d'ajouter @XmlTransient à la variable
HomeIsWhereThePcIs

8

Vous devez également configurer la classe ModeleREPavec @XmlAccessorType(XmlAccessType.FIELD)comme vous l'avez fait avec la classe TimeSeries.

Jetez un œil à OOXS


8

Si nous utilisons les annotations ci-dessous et supprimons l'annotation «@XmlElement», le code devrait fonctionner correctement et le XML résultant aurait les noms d'élément similaires au membre de la classe.

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

Dans le cas où l'utilisation de "@XmlElement" est vraiment nécessaire, veuillez le définir au niveau du champ et le code devrait fonctionner parfaitement. Ne définissez pas l'annotation en haut de la méthode getter.

Avait essayé les deux approches mentionnées ci-dessus et réussi à résoudre le problème.


7

"La classe a deux propriétés du même nom exception" peut se produire lorsque vous avez un membre de classe x avec un niveau d'accès public et un getter / setter pour le même membre.

En règle générale de Java, il n'est pas recommandé d'utiliser un public niveau d'accès avec les getters et les setters.

Vérifiez ceci pour plus de détails: Propriété publique VS Propriété privée avec getter?

Pour résoudre ce problème:

  1. Changez le niveau d'accès de votre membre en privé et gardez votre getter / setter
  2. Supprimer le getter et le setter du membre

6

Ce sont les deux propriétés que JAXB examine.

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

et

protected java.util.List testjaxp.ModeleREP.timeSeries

Cela peut être évité en utilisant l'annotation JAXB à la méthode get comme mentionné ci-dessous.

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

5

déclarez simplement les variables membres comme privées dans la classe que vous souhaitez convertir en XML. Bon codage


Cela devrait être la solution acceptée. Si vous déclarez votre variable membre publique, JABX l'analysera en plus des méthodes annotées getter / setter et crachera l'exception. C'est un excellent exemple où les concepteurs de bibliothèques jabx ont fait un effort supplémentaire pour réfléchir en essayant de créer de la flexibilité et ont fini par faciliter des configurations invalides. J'ai résolu le problème par moi-même en modifiant une ligne de code à la fois, en remontant à la variable membre.
Vortex

4

Même problème que j'ai rencontré, j'ai ajouté

@XmlRootElement(name="yourRootElementName")

@XmlAccessorType(XmlAccessType.FIELD)

et maintenant cela fonctionne.


3

Cela fonctionnera lorsque vous placerez votre annotation avant les getters et que vous la supprimerez des attributs protégés:

protected String codingScheme;

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

Moi aussi, je rencontre le même problème. J'ai également observé que lorsque l'annotation est marquée sur les attributs, je vois cela. Cela signifie-t-il qu'il doit toujours être placé avant les getters ?.
Pavan Dittakavi

@Pavan Oui, je pense. Sinon, ça me cause les mêmes problèmes que toi
Lilia

2

Je viens de rencontrer ce problème et je l'ai résolu.

La source du problème est que vous avez à la fois XmlAccessType.FIELD et des paires de getters et de setters. La solution est de supprimer les setters et d'ajouter un constructeur par défaut et un constructeur qui prend tous les champs.


J'ai eu la même erreur et l'annotation que vous avez mentionnée l'a résolue, merci!
gyorgyabraham

1

J'ai eu une classe de service avec la signature ci-dessous "

@WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {

En cours d'exécution, j'ai eu la même erreur pour les FetchIQAStatusResponseVOchamps. Je viens d'ajouter une ligne en plus de FetchIQAStatusResponseVO:

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

et cela a résolu le problème.


1

ModeleREP#getTimeSeries()doivent être avec @Transientannotation. Cela aiderait.


0

Annoter avec @XmlTransientrésout ce problème

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

Regardez http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html pour plus de détails


1
Je pense que c'est plus un hack qu'une solution. Cela dit à jaxb d'ignorer la méthode, au lieu de lui faire prendre conscience que c'est la même chose.
Hans Wouters

Hack ou pas, c'est la meilleure solution pour contourner quelque chose qui ne peut pas être décrit comme quelque chose de moins qu'un bug, j'ai utilisé @XmlAccessorType (XmlAccessType.FIELD) qui était principalement ignoré et l'ajout de @XmlTransient à chaque propriété était le seul moyen de réparer ce problème. Merci!
Ralph Ritoch

0

Un moyen rapide et simple de résoudre ce problème consiste à supprimer le @XmlElement(name="TimeSeries")du haut de l'instruction de déclaration de variable protected List<TimeSeries> timeSeries;vers le haut de son getter,public List<TimeSeries> getTimeSeries() .

Ainsi, votre ModeleREPclasse ressemblera à:

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

J'espère que ça aide!


Vous mentionnez «Une manière simple». Curieux, y a-t-il un autre moyen de s'en sortir - ou une autre annotation qui pourrait être exploitée ?.
Pavan Dittakavi

0

J'ai fait des essais et des erreurs et j'ai conclu que vous ne devez utiliser que l'un des deux @XMLElementou @XmlAccessorType(XmlAccessType.FIELD).

Quand utiliser lequel?

cas 1 : Si vos noms de champ et le nom d'élément que vous souhaitez utiliser dans un fichier xml sont différents, vous devez utiliser @XMLElement(name="elementName"). Comme cela liera les champs avec ce nom d'élément et s'affichera dans un fichier XML.

cas 2 : Si les noms de champs et le nom d'élément respectif dans xml sont tous les deux identiques, vous pouvez simplement utiliser@XmlAccessorType(XmlAccessType.FIELD)


0

De nombreuses solutions ont été proposées, et les internes sont brièvement touchés par @Sriram et @ptomli également. Je veux juste ajouter quelques références au code source pour aider à comprendre ce qui se passe sous le capot.

Par défaut (c'est-à-dire pas d'annotations supplémentaires utilisées du tout sauf @XmlRootElementsur la classe racine), JABX essaie de rassembler les éléments exposés de deux manières:

  1. champs publics
  2. méthodes getter nommées selon la convention et ayant une méthode setter correspondante.

Notez que si un champ est (ou une méthode retourne) null , il ne sera pas écrit dans la sortie.

Maintenant si @XmlElement est utilisé, les choses non publiques (qui peuvent être des champs ou des méthodes getter) peuvent également être rassemblées.

Mais les deux méthodes, à savoir les champs et les méthodes getter, ne doivent pas entrer en conflit l'une avec l'autre. Sinon, vous obtenez l'exception .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.