java - 为什么我不能将这个简单的对象映射到 Java/Jersey 中的 XML 文本?

标签 java jaxb jersey moxy

我有一个用 Java 中的 Jersey 创建的 REST API。 对于一个请求,我想以 JSON 格式返回一对坐标元组的列表。 为此,我有一个类,它是 ArrayList、Tuple2 类和 Coords 类的包装器。 我使用 javax.xml.bind.annotations 自动生成类的 XML/JSON。

但由于我不明白我的 Coords 类无法映射到 XML。

我尝试了不同类型的属性(Integers 而不是 int),在不同位置(在属性和在 getter 之前)和不同的 XmlAccessType(PROPERTY 而不是 NONE),但结果是相同的。

这是我的坐标类:

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.

感谢您的帮助。

最佳答案

您的问题来自于滥用 xml 注释。您正在定义 Tuple2通过使用 @XmlRootElement 注释它来成为 xml 根元素,通过使用 @XmlAttribute 注释 get 方法,将其字段设置为 xml 属性。 。翻译过来就是:

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

现在,两个字段的类型都是 Coords ,通过注释 Coords 将其声明为另一个 xml 元素与 @XmlRootElement 一起上课,其字段为 xml 属性。当Coords被序列化为 xml,它将是:

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

序列化 Tuple2 时出现问题。它的字段应该是 xml 属性,但是 Coords是另一个 xml 元素。 Xml 属性不能包含嵌套元素,只能包含值。

解决方案

根据您的需要,您可以通过两种不同的方式解决此问题。不过,我不推荐第二种方法,因为它很奇怪(即使它有效)并且会在客户端产生额外的工作(请参阅下面的解释)。

第一种方法

注释 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返回。

关于java - 为什么我不能将这个简单的对象映射到 Java/Jersey 中的 XML 文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58580115/

相关文章:

java - java将数据写入Excel工作表

java - 我如何可视化 jar(不是插件)依赖项?

java - 如何在解码时捕获多次出现的 xml 到 pojo?

java - 将文档流发送到 Jersey @POST 端点

java - 在 C++ 这样的语言中 (a ^ (1 << b)) 实际上做了什么?

java - Ruby 类实例上的等效操作(对于 Java)

java - 包含 XML 内容的 CXF Web 服务响应

java - 无法将 xml 转换为 java 对象

java - 使用 JSONObject 放置/获取字节数组值

java - 将 WAR 文件上传到 WebSphere 6.1 时出现问题