Jaxb, Lớp có hai thuộc tính cùng tên


120

với jaxb, tôi cố gắng đọc tệp xml chỉ có một vài phần tử trong tệp xml là thú vị, vì vậy tôi muốn bỏ qua nhiều phần tử

nội dung xml

xml tôi cố gắng đọc

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

lớp học của tôi

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

khi tôi cố đọc tệp xlm, tôi nhận được

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

tôi không hiểu lỗi này

chỉnh sửa: tôi sử dụng jaxb-impl-2.1.12

ok bây giờ tôi không có bất kỳ lỗi nào, nhưng khi tôi kiểm tra đối tượng của mình, timeSeries là null ...

vì vậy có thể jaxb dường như có vấn đề với flx?

Câu trả lời:


204

Tôi cũng phải đối mặt với vấn đề như thế này và tôi đã đặt ra điều này.

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

Điều này sẽ hoạt động 100%


8
Tôi gặp vấn đề tương tự. Và ngay cả khi nó hoạt động khi chúng ta thêm chỉ @XmlAccessorType (XmlAccessType.FIELD)
Ram Dutt Shukla

2
Tôi giải quyết vấn đề bằng cách loại bỏ các @XmlAccessorType(XmlAccessType.FIELD)chú thích
Hans Wouters

Nghe có vẻ lạ, nhưng tôi cũng đã loại bỏ ngoại lệ này bằng cách giảm cặp chú thích \ @XmlRootElement @XmlAccessorType (XmlAccessType.FIELD) xuống chỉ \ @XmlRootElement
Alex InTechno

3
Gặp phải vấn đề tương tự với các lớp Bên trong cho Chú thích JAXB. Đặt @XmlAccessorType (XmlAccessType.FIELD) trên các lớp bên trong đã hoạt động!
Shoaib Khan

Tuyệt vời, cảm ơn bạn rất nhiều. Kết hợp với Lombok rất hữu ích
Michael Hegner 13/12/19

25

Bạn không chỉ định phiên bản JAXB-IMPL mà bạn đang sử dụng, nhưng một lần tôi gặp vấn đề tương tự (với jaxb-impl 2.0.5) và đã giải quyết nó bằng cách sử dụng chú thích ở cấp getter thay vì sử dụng nó ở cấp thành viên.


Đó là chính xác, tôi vừa xóa chú thích khỏi thành viên và đặt nó ở cấp độ setter và nó đã hoạt động.
Varun

22

Tôi cũng đã thấy một số vấn đề tương tự như thế này.

Tôi nghĩ rằng, đó là vì trong những nơi mà chúng ta sử dụng " @XmlElement " chú thích trong (đậu) lớp.

Và tôi nghĩ, JAXB (bộ xử lý chú thích) coi trường thành viên & phương thức getter của cùng một phần tử trường là các thuộc tính khác nhau, khi chúng tôi sử dụng chú thích @XMLElement ở cấp trường và ném ngoại lệ IllegalAnnotationExceptions .

Thông báo ngoại lệ:

Lớp có hai thuộc tính của cùng một tên "chuỗi thời gian"

Tại phương pháp Getter:

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

Tại Trường Thành viên:

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

Giải pháp: Thay vì sử dụng @XmlElement trong trường , hãy sử dụng nó trong phương thức getter .


16

vừa thêm cái này vào lớp của tôi

@XmlAccessorType(XmlAccessType.FIELD)

làm việc như một cham


Hoạt động cùng với chú thích @Data của lombok.
digz6666,

16

Có nhiều giải pháp nhưng về cơ bản nếu bạn chú thích trên khai báo biến thì bạn cần @XmlAccessorType(XmlAccessType.FIELD), nhưng nếu bạn thích chú thích phương thức get- hoặc set-thì bạn không cần.

Vì vậy, bạn có thể làm:

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

Hoặc là:

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

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

Tuyệt vời. Cảm ơn :) +1
Anish B.

11

JAXB của bạn đang xem xét cả getTimeSeries()phương pháp và thành viên timeSeries. Bạn không cho biết bạn đang sử dụng triển khai JAXB nào hoặc cấu hình của nó, nhưng ngoại lệ khá rõ ràng.

tại public java.util.List testjaxp.ModeleREP.getTimeSeries ()

tại protected java.util.List testjaxp.ModeleREP.timeSeries

Bạn cần phải định cấu hình nội dung JAXB của mình để sử dụng các chú thích (theo ý bạn @XmlElement(name="TimeSeries")) và bỏ qua các phương thức công khai.


tôi đã làm: @XmlElement (name = "TimeSeries") Danh sách được bảo vệ <TimeSeries> timeSeries;
redfox26

4
còn tôi thay đổi (XmlAccessType.FIELD) đến (XmlAccessType.NONE), tôi có thể giữ XmlElement ở cấp thành viên
redfox26

Tôi cũng cần thêm @XmlTransient vào biến
HomeIsWhereThePcIs

8

Bạn cần phải cấu hình lớp ModeleREPcũng @XmlAccessorType(XmlAccessType.FIELD)như bạn đã làm với lớp TimeSeries.

Hãy xem OOXS


8

Nếu chúng tôi sử dụng các chú thích bên dưới và xóa chú thích "@XmlElement", mã sẽ hoạt động bình thường và XML kết quả sẽ có tên phần tử tương tự như thành viên lớp.

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

Trong trường hợp thực sự cần sử dụng "@XmlElement", vui lòng xác định nó là cấp trường và mã sẽ hoạt động hoàn hảo. Không xác định chú thích trên đầu phương thức getter.

Đã thử cả hai cách tiếp cận trên được đề cập và đã khắc phục được sự cố.


7

"Lớp có hai thuộc tính cùng tên là ngoại lệ" có thể xảy ra khi bạn có một thành viên lớp x với mức truy cập công khai và getter / setter cho cùng một thành viên.

Theo quy tắc chung của java, không nên sử dụng mức truy cập công khai cùng với getters và setters.

Kiểm tra phần này để biết thêm chi tiết: Tài sản công VS Sở hữu tư nhân với getter?

Để khắc phục điều đó:

  1. Thay đổi cấp độ truy cập của thành viên của bạn thành riêng tư và giữ getter / setter của bạn
  2. Loại bỏ getter và setter của thành viên

6

Đây là hai thuộc tính mà JAXB đang xem xét.

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

protected java.util.List testjaxp.ModeleREP.timeSeries

Điều này có thể tránh được bằng cách sử dụng phương thức get của JAXB annotation giống như đã đề cập bên dưới.

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

5

chỉ cần khai báo các biến thành viên thành private trong lớp mà bạn muốn chuyển đổi sang XML. Viết mã vui vẻ


Đây nên là giải pháp được chấp nhận. Nếu bạn khai báo biến thành viên của mình là public, JABX sẽ phân tích cú pháp nó cùng với các phương thức chú thích getter / setter và loại bỏ ngoại lệ. Đó là một ví dụ tuyệt vời trong đó (các) nhà thiết kế thư viện jabx đã đi xa hơn trong việc phản ánh cố gắng tạo ra sự linh hoạt và cuối cùng đã tạo điều kiện cho các cấu hình không hợp lệ. Tôi đã tự khắc phục sự cố bằng cách thay đổi một dòng mã tại thời điểm đó, truy xuất lại biến thành viên.
Vortex

4

Tôi đã phải đối mặt với cùng một vấn đề

@XmlRootElement(name="yourRootElementName")

@XmlAccessorType(XmlAccessType.FIELD)

và bây giờ nó đang hoạt động.


3

Nó sẽ hoạt động khi bạn đặt chú thích của mình trước getters và xóa nó khỏi các thuộc tính được bảo vệ:

protected String codingScheme;

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

Tôi cũng đang gặp phải vấn đề tương tự. Tôi cũng đã quan sát thấy rằng khi chú thích được đánh dấu trên các thuộc tính, tôi thấy điều này. Điều này có nghĩa là nó luôn luôn phải được đặt trước những người đứng đầu?
Pavan Dittakavi

@Pavan Vâng, tôi nghĩ vậy. Nếu không, nó gây ra cho tôi những vấn đề tương tự như bạn
Lilia

2

Tôi vừa gặp phải vấn đề này và đã giải quyết nó.

Nguồn gốc của vấn đề là bạn có cả XmlAccessType.FIELD và các cặp getters và setters. Giải pháp là loại bỏ setters và thêm một hàm tạo mặc định và một hàm tạo nhận tất cả các trường.


Tôi đã gặp lỗi tương tự và chú thích mà bạn đề cập đã giải quyết được nó, cảm ơn!
gyorgyabraham

1

Tôi đã có một lớp dịch vụ với chữ ký như bên dưới "

@WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {

Khi chạy, tôi gặp lỗi tương tự cho FetchIQAStatusResponseVOcác trường. Tôi vừa thêm một dòng trên đầu trang FetchIQAStatusResponseVO:

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

và điều này đã giải quyết vấn đề.


1

ModeleREP#getTimeSeries()phải có @Transientchú thích. Điều đó sẽ giúp.


0

Chú thích với @XmlTransientgiải quyết vấn đề đó

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

Hãy xem http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html để biết thêm chi tiết


1
Tôi nghĩ đây là một vụ hack hơn là một giải pháp. Điều này yêu cầu jaxb bỏ qua phương thức, thay vì làm cho nó biết rằng nó là cùng một thứ.
Hans Wouters

Hack hay không Đây là giải pháp tốt nhất để khắc phục một thứ không thể được mô tả là bất kỳ lỗi nào, tôi đã sử dụng @XmlAccessorType (XmlAccessType.FIELD) mà hầu như bị bỏ qua và thêm @XmlTransient vào từng thuộc tính là cách duy nhất để sửa chữa vấn đề này. Cảm ơn!
Ralph Ritoch

0

Một cách nhanh chóng và đơn giản để khắc phục sự cố này là loại bỏ @XmlElement(name="TimeSeries")từ đầu câu lệnh khai báo biến protected List<TimeSeries> timeSeries;đến đầu getter của nó public List<TimeSeries> getTimeSeries(),.

Vì vậy, ModeleREPlớp của bạn sẽ trông giống như:

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

Hy vọng nó giúp!


Bạn đề cập đến 'Một cách đơn giản'. Tò mò, có cách nào khác để giải quyết vấn đề này - chú thích này có thể được tận dụng không ?.
Pavan Dittakavi

0

Tôi đã thử và sai và nhận được kết luận rằng, bạn chỉ phải sử dụng một trong hai @XMLElementhoặc @XmlAccessorType(XmlAccessType.FIELD).

Khi nào sử dụng cái nào?

Trường hợp 1 : Nếu tên trường và tên phần tử bạn muốn sử dụng trong tệp xml khác nhau thì bạn phải sử dụng @XMLElement(name="elementName"). Vì điều này sẽ liên kết các trường với tên phần tử đó và hiển thị trong tệp XML.

trường hợp 2 : Nếu cả hai tên trường và tên phần tử tương ứng trong xml đều giống nhau thì bạn chỉ cần sử dụng@XmlAccessorType(XmlAccessType.FIELD)


0

Nhiều giải pháp đã được đưa ra và nội bộ cũng được @Sriram và @ptomli đề cập đến. Tôi chỉ muốn thêm một vài tài liệu tham khảo vào mã nguồn để giúp hiểu những gì đang xảy ra.

Theo mặc định (tức là không có chú thích bổ sung nào được sử dụng ngoại trừ @XmlRootElementtrên lớp gốc), JABX cố gắng điều chỉnh những thứ được hiển thị thông qua hai cách:

  1. lĩnh vực công cộng
  2. phương thức getter được đặt tên theo quy ước và có phương thức setter tương ứng.

Lưu ý rằng nếu một trường là (hoặc phương thức trả về) null, nó sẽ không được ghi vào đầu ra.

Bây giờ nếu @XmlElementđược sử dụng, những thứ không công khai (có thể là trường hoặc phương thức getter) cũng có thể được sắp xếp.

Nhưng hai cách, tức là các trường và phương thức getter, không được xung đột với nhau. Nếu không, bạn sẽ có ngoại lệ .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.