Jersey/JAXB 讨厌矩形
Jersey/JAXB hates Rectangle
我有一个 Java 应用程序,它使用 Jersey 来提供 REST 服务。我有几个 REST 端点,所有这些端点 return 有效 JSON (所需格式)。我们有一个新的端点,一个 GET,return 有效 JSON,除了一个元素,一个 Java 矩形。这是我们得到的响应:
[
{
"customers": {
"current": 2,
"max": 16
},
"format": "ABCD",
"dataPoints": 20,
"window": "java.awt.Rectangle[x=50,y=50,width=400,height=300]"
}
]
如您所见,矩形无效 JSON。我尝试了几件事,但 none 奏效了。我尝试过的事情包括在 class 上的矩形元素上添加 @XmlRootElement
、@XmlElement
和 @XmlAttribute
。唯一要做的就是将格式错误的 JSON 移动到输出的顶部。
我怀疑它不起作用,因为矩形 class 在其 class 声明中没有 @XmlRootElement
,因此 JAXB 无法将其正确转换为 XML(然后进入JSON)。如果是这种情况,我是否需要从 Rectangle 继承只是为了包含该注释? JAXB 开发人员似乎已经考虑了内置类型。我的假设是否正确,或者是否有其他解决方案?
另一种解决方案可能是自己进行 JSON 转换,然后 return 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。
按照this article你可以这样解决问题
JAXB 开箱即用,无法 marshall/unmarshall java.awt.Rectangle
。
因为我们无法更改 Rectangle
class,我们将编写新的 class、MyRectangle
,JAXB 知道如何 marshall/unmarshall。
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
在 Rectangle
和 MyRectangle
之间转换:
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 在 marshalling/unmarshalling 时使用我们的 RectangleXmlAdapter
Rectangle
属性。例如:
@XmlJavaTypeAdapter(RectangleXmlAdapter.class)
private Rectangle window;
那么这个 window
属性 会有这样的 XML 表示:
<window>
<x>50</x>
<y>50</y>
<width>400</width>
<height>300</height>
</window>
然后(通过一些 Jersey-magic)这样的 JSON 表示:
"window": {
"x": 50,
"y": 50,
"width": 400,
"height": 300
}
我有一个 Java 应用程序,它使用 Jersey 来提供 REST 服务。我有几个 REST 端点,所有这些端点 return 有效 JSON (所需格式)。我们有一个新的端点,一个 GET,return 有效 JSON,除了一个元素,一个 Java 矩形。这是我们得到的响应:
[
{
"customers": {
"current": 2,
"max": 16
},
"format": "ABCD",
"dataPoints": 20,
"window": "java.awt.Rectangle[x=50,y=50,width=400,height=300]"
}
]
如您所见,矩形无效 JSON。我尝试了几件事,但 none 奏效了。我尝试过的事情包括在 class 上的矩形元素上添加 @XmlRootElement
、@XmlElement
和 @XmlAttribute
。唯一要做的就是将格式错误的 JSON 移动到输出的顶部。
我怀疑它不起作用,因为矩形 class 在其 class 声明中没有 @XmlRootElement
,因此 JAXB 无法将其正确转换为 XML(然后进入JSON)。如果是这种情况,我是否需要从 Rectangle 继承只是为了包含该注释? JAXB 开发人员似乎已经考虑了内置类型。我的假设是否正确,或者是否有其他解决方案?
另一种解决方案可能是自己进行 JSON 转换,然后 return 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。
按照this article你可以这样解决问题
JAXB 开箱即用,无法 marshall/unmarshall java.awt.Rectangle
。
因为我们无法更改 Rectangle
class,我们将编写新的 class、MyRectangle
,JAXB 知道如何 marshall/unmarshall。
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
在 Rectangle
和 MyRectangle
之间转换:
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 在 marshalling/unmarshalling 时使用我们的 RectangleXmlAdapter
Rectangle
属性。例如:
@XmlJavaTypeAdapter(RectangleXmlAdapter.class)
private Rectangle window;
那么这个 window
属性 会有这样的 XML 表示:
<window>
<x>50</x>
<y>50</y>
<width>400</width>
<height>300</height>
</window>
然后(通过一些 Jersey-magic)这样的 JSON 表示:
"window": {
"x": 50,
"y": 50,
"width": 400,
"height": 300
}