なぜ私は、Java /ジャージーでのXMLのテキストに、この単純なオブジェクトをマップすることはできませんか?

hforrat:

私はJavaで作成されたジャージーとREST APIを持っています。1つの要求のために私はJSONの座標のペアのタプルのリストを返すようにしたいと思います。このために、私はラッパーのクラス持ちArrayListTuple2クラスとCoordsクラスを。私が使用しjavax.xml.bind.annotations、自動的に私のクラスのXML / JSONを生成します。

しかし、私は私の理解していないという理由でCoordsクラスを私はXMLにマッピングすることはできません。

私は、異なる属性の種類(しようとしたIntegersの代わりをint有する)@XmlAttribute(属性の前とゲッターの前に)異なる場所で、異なるXmlAccessTypePROPERTY代わりにNONE)が、結果は同じでした。

ここに私のCOORDSクラスは次のとおりです。

package model;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAttribute;
import static javax.xml.bind.annotation.XmlAccessType.NONE;

@XmlRootElement
@XmlAccessorType(NONE)
public class Coords {
    @XmlAttribute private int x;
    @XmlAttribute private int y;

    public Coords(final int x, final int y) {
        this.x = x;
        this.y = y;
    }

    public Coords() {
        this.x = 0;
        this.y = 0;
    }

    public int getX() {
        return this.x;
    }

    public int getY() {
        return this.y;
    }
}

そして、ここで、それは私のTuple2に存在している方法です

package model;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAttribute;
import static javax.xml.bind.annotation.XmlAccessType.NONE;

@XmlRootElement
@XmlAccessorType(NONE)
public class Tuple2 {
    private Coords c1;
    private Coords c2;
// ...
    @XmlAttribute 
    public Coords getFirst() {
        return this.c1;
    }

    @XmlAttribute 
    public Coords getSecond() {
        return this.c2;
    }
// ...
}

ここではエラーメッセージは次のとおりです。

[EL Warning]: moxy: 2019-10-27 15:01:08.586--javax.xml.bind.JAXBException: 
Exception Description: The @XmlAttribute property first in type model.Tuple2 must reference a type that maps to text in XML. model.Coords cannot be mapped to a text value.
 - with linked exception:
[Exception [EclipseLink-50096] (Eclipse Persistence Services - 2.7.4.v20190115-ad5b7c6b2a): org.eclipse.persistence.exceptions.JAXBException
Exception Description: The @XmlAttribute property first in type model.Tuple2 must reference a type that maps to text in XML.  model.Coords cannot be mapped to a text value.]
oct. 27, 2019 3:01:08 PM org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo
GRAVE: MessageBodyWriter not found for media type=application/json, type=class model.ActionList, genericType=class model.ActionList.

ご協力ありがとうございました。

ahoxha:

あなたの問題は、XML注釈の誤用から来ています。あなたは定義されているTuple2と、それに注釈を付けることによって、XMLのルート要素である@XmlRootElementとgetメソッドに注釈を付けることにより、XML属性であることを、そしてそのフィールド@XmlAttributeどちらに変換します。

<tuple2 first="first_attributes_vale" second="second_attributes_value" />

今、両方のフィールドがタイプであるCoords注釈を付けることによって、他のXML要素であると宣言されている、Coordsとのクラスを@XmlRootElement、そしてそのフィールドは、XML属性であることを。場合はCoords、XMLにシリアライズされます、それは次のようになります。

<coords x="value" y="value" />

直列化時に問題が発生しますTuple2そのフィールドは、XML属性のはずが、されているCoords別のXML要素です。XML属性は、ネストされた要素が、唯一の値を含めることはできません。

解決

あなたが欲しいものに応じて、2つの異なる方法でこの問題を解決することができます。私はそれは奇妙だから(それが動作するにもかかわらず)、第二のアプローチをお勧めしませんし、クライアント側に余分な労力がかかります、が、(以下の説明を参照してください)。

最初のアプローチ

注釈を付けるgetFirst()getSecond()持つメソッド@XmlElement注釈を。

package model;

import static javax.xml.bind.annotation.XmlAccessType.NONE;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(NONE)
public class Tuple2 {
    private Coords c1;
    private Coords c2;

    public Tuple2(Coords c1, Coords c2) {
        this.c1 = c1;
        this.c2 = c2;
    }

    public Tuple2() {
        c1 = new Coords(0, 0);
        c2 = new Coords(0, 0);
    }

    @XmlElement
    public Coords getFirst() {
        return this.c1;
    }

    @XmlElement
    public Coords getSecond() {
        return this.c2;
    }
}

これは、このようなことがルックス結果を生成します:

<tuple2>
    <first x="2" y="4"/>
    <second x="12" y="12"/>
</tuple2>

第二のアプローチ

これは、それを解決するための奇妙な方法です。それは動作しますが、の値があるため、それは、クライアント側に余分な努力を招きCoords、文字列値としてエンコードされ、受信側で解析する必要があります。

戻り値の型に変更getFirst()getSecond()なるためのメソッドをStringオーバライドtoString()する方法をCoords

package model;

import static javax.xml.bind.annotation.XmlAccessType.NONE;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(NONE)
public class Tuple2 {
    private Coords c1;
    private Coords c2;

    public Tuple2(Coords c1, Coords c2) {
        this.c1 = c1;
        this.c2 = c2;
    }

    public Tuple2() {
        c1 = new Coords(0, 0);
        c2 = new Coords(0, 0);
    }

    @XmlAttribute
    public String getFirst() {
        return this.c1.toString();
    }

    @XmlAttribute
    public String getSecond() {
        return this.c2.toString();
    }
}

オーバーライドtoString()する方法をCoords

package model;

import static javax.xml.bind.annotation.XmlAccessType.NONE;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(NONE)
public class Coords {
    @XmlAttribute private int x;
    @XmlAttribute private int y;

    public Coords(final int x, final int y) {
        this.x = x;
        this.y = y;
    }

    public Coords() {
        this.x = 0;
        this.y = 0;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Coords [x=");
        builder.append(x);
        builder.append(", y=");
        builder.append(y);
        builder.append("]");
        return builder.toString();
    }
}

これは、このような結果を生成します:

<tuple2 first="Coords [x=2, y=4]" second="Coords [x=12, y=12]"/>

属性の値は、firstsecond何になるtoString()方法Coordsを返します。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=331096&siteId=1