假设我在JAX-RS 1环境中有一个数据类(与Jackson提供商一起使用RestEasy 2),如下所示:
class Foo {
int id;
String name;
Bar bar;
...
}
Bar
:
class Bar {
int one;
String two;
}
现在我希望Bar
以特殊方式序列化(可能取决于所请求的媒体类型(或取决于月亮的相位),我会写一个MessageBodyWriter<Bar>
@Provider
@Produces("application/json")
public class BarWriter implements MessageBodyWriter<Bar> {
...
}
如果{<1}}单独请求,则可以很好地工作,如
Bar
但是当我在
中请求@GET @Path("bar")
public Bar getBar() { return new Bar(...); }
时
Foo
忽略邮件正文编写器。
现在我想要的是,当我返回@GET @Path("foo")
public Foo getFoo() { return new Foo(...); }
或MessageBodyWriter
Foo
我认为后者可以通过为List<Bar>
案例编写自定义MessageBodyWriter
来实现,但对于前一种情况,我无法为包含所有应用程序类编写消息体编写器一个List
字段。
关于如何解决这个问题的任何想法?我也试图在Bar
实例上使用Jackson序列化程序,但看起来这甚至没有被RestEasy注册(然后,我认为这种方式太脆弱了。)
答案 0 :(得分:6)
不幸的是,这不是邮件正文编写者的工作方式。 JAX-RS实现将根据资源方法返回的类型定位要在序列化中使用的编写器。因此,在您的情况下,使用此资源方法为Bar
定义自定义编写器:
@GET @Path("bar")
public Bar getBar() { return new Bar(...); }
JAX-RS提供程序将使用您的自定义编写器序列化Bar
。但是对于此资源方法:
@GET @Path("foo")
public Foo getFoo() { return new Foo(...); }
您没有定义自定义编写器,序列化将由第一个匹配(默认)提供程序处理,该提供程序可以处理返回类和内容类型的组合。需要记住的一件事是,与典型的JSON和XML序列化库不同,JAX-RS实体提供程序 不 是递归的。 Aka,对于在资源方法中返回的给定对象A
,提供程序将尝试为A
找到自定义编写器 ,而不是针对包含的任何类型在A
中作为变量。
由于您使用的是Jackson,为什么不为您的Bar
类定义自定义序列化程序?这将处理您描述的几乎所有情况:
public class BarSerializer extends JsonSerializer<Bar> {
@Override
public void serialize(final Bar value, final JsonGenerator jgen,
final SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeStartObject();
jgen.writeFieldName("myBar");
jgen.writeString(value.getTwo());
jgen.writeEndObject();
}
}
你告诉杰克逊这样使用这个自定义序列化器:
@JsonSerialize(using=BarSerializer.class)
class Bar {
int one;
String two;
}
最后,请不要忘记,如果您希望以序列化的形式返回JSON,那么您还需要自定义JsonDeserializer
。
要使其发挥作用,您需要在类路径中使用jackson-mapper
和jackson-jaxrs
个jar(也可能需要jackson-core
个)。
答案 1 :(得分:1)
JAX-RS运行时只查找资源方法返回的对象的MessageBodyWriter
(请参阅规范中的sectioin&#34; 4.2.2 Message Body Writer&#34;)然后单个MessageBodyWriter
可以完全控制要返回给客户端的整个对象图的序列化。
为了实现您想要的行为,您需要每种媒体类型的自定义MessageBodyWriter
,每当遇到特定类型时,愿意将对象图的一部分的序列化委托给另一个编写器。图表,然后恢复自己的逻辑。获取特定类型的委托编写者不是一个大问题(注入javax.ws.rs.ext.Providers
并调用getMessageBodyWriter()
),但我不认为现有的xml / json / etc序列化程序在实现这种扩展时,所以我猜你不能继续它们。为此重新实现xml marshaller也不是一个有吸引力的选择。
答案 2 :(得分:-1)
请参阅以下文章,为Java对象的序列化编写自定义消息正文编写器。
http://h2labz.blogspot.in/2014/12/marshalling-java-to-json-in-jax-rs.html