【问题标题】:Jersey/JAXB hates RectangleJersey/JAXB 讨厌矩形
【发布时间】:2018-04-18 23:05:49
【问题描述】:

我有一个使用 Jersey 提供 REST 服务的 Java 应用程序。我有几个 REST 端点,所有这些端点都返回有效的 JSON(所需的格式)。我们有一个新的端点,一个 GET,它返回有效的 JSON,除了一个元素,一个 Java 矩形。这是我们得到的响应:

[
    {
        "customers": {
            "current": 2,
            "max": 16
        },
        "format": "ABCD",
        "dataPoints": 20,
        "window": "java.awt.Rectangle[x=50,y=50,width=400,height=300]"
    }
]

如您所见,该 Rectangle 不是有效的 JSON。我已经尝试了几件事,但都没有奏效。我尝试过的方法包括在类的 Rectangle 元素上添加 @XmlRootElement@XmlElement@XmlAttribute。唯一要做的就是将格式错误的 JSON 移到输出的顶部。

我怀疑它不起作用,因为 Rectangle 类在其类声明中没有 @XmlRootElement,因此 JAXB 无法正确将其转换为 XML(然后转换为 JSON)。如果是这种情况,我是否需要从 Rectangle 继承以包含该注释?似乎 JAXB 开发人员会考虑内置类型。我的假设是否正确,还是有其他解决方案?

【问题讨论】:

  • 您需要为java.awt.Rectangle 创建一个XmlAdapter。见this article
  • 谢谢,@ThomasFritsch。我精确地复制了这个例子,现在window 显示为一个空数组。那是错误的,但我真的不知道如何调试这个错误。
  • 我需要将所有的 setter 添加到替代类(文章没有提到这些)。添加它们后,一切正常! @ThomasFritsch,如果您将第一个回复变成答案,我会将其标记为解决方案。 :)

标签: java jaxb jersey


【解决方案1】:

按照this article你可以解决这样的问题。

JAXB 开箱即用,无法编组/解组 java.awt.Rectangle

因为我们无法更改 Rectangle 类,所以我们将编写一个新类 MyRectangle,JAXB 知道如何编组/取消编组。

public class MyRectangle {

    private int x;
    private int y;
    private int width;
    private int height;

    public MyRectangle() {
    }

    public MyRectangle(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}

那么我们需要一个XmlAdapter 用于在RectangleMyRectangle 之间进行转换:

public class RectangleXmlAdapter extends XmlAdapter<MyRectangle, Rectangle> {

    @Override
    public Rectangle unmarshal(MyRectangle v) throws Exception {
        if (v == null)
            return null;
        return new Rectangle(v.getX(), v.getY(), v.getWidth(), v.getHeight());
    }

    @Override
    public MyRectangle marshal(Rectangle v) throws Exception {
        if (v == null)
            return null;
        return new MyRectangle(v.x, v.y, v.width, v.height);
    }
}

最后,您使用@XmlJavaTypeAdapter 注释告诉 JAXB 在编组/解组时使用我们的 RectangleXmlAdapter Rectangle 属性。例如:

@XmlJavaTypeAdapter(RectangleXmlAdapter.class)
private Rectangle window;

那么这个window 属性将有一个像这样的XML 表示:

<window>
    <x>50</x>
    <y>50</y>
    <width>400</width>
    <height>300</height>
</window>

然后(通过一些泽西魔术)像这样的 JSON 表示:

"window": {
    "x": 50,
    "y": 50,
    "width": 400,
    "height": 300
}

【讨论】:

  • 谢谢!我已经按照这篇文章让这些东西正常工作,但感谢您的深入回答!我想指出,一旦 JAXB 可以将类转换为 XML,它就可以快速将其转换为 JSON,这正是我所需要的。再次感谢!
  • 我已根据您关于 XML-JSON-conversion 的说明更新了我的答案。
【解决方案2】:

另一种解决方案可能是自己进行 JSON 转换,然后将 JSON 字符串作为响应的实体返回,如下所示。

@Path("/rectangle")
@Produces(MediaType.APPLICATION_JSON)
@GET
public Response getRect() {

    Rectangle r = new Rectangle();
    Gson gson = new Gson();
    String jsonRect = gson.toJson(r);
    return Response.status(Status.OK).entity(jsonRect).build();
}

因此根本不使用 JAXB。

【讨论】:

  • 感谢您的建议,但这不起作用。我的 REST 端点调用另一个类,该类具有它需要返回的数据。使用您的建议,永远不会调用 getRect() (可能是因为它返回的是字符串而不是矩形?)。还是谢谢。
猜你喜欢
  • 1970-01-01
  • 2010-11-19
  • 2013-12-11
  • 2011-02-02
  • 1970-01-01
  • 2021-05-07
  • 2016-08-24
  • 2012-09-02
  • 2010-10-12
相关资源
最近更新 更多