2013-03-05 62 views
5

具体MessageBodyWriter说我有在一个JAX-RS 1个环境(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> { 
    ... 
} 

如果请求对自己喜欢的

@GET @Path("bar") 
public Bar getBar() { return new Bar(...); } 

Bar但是,当我要求Foo

@GET @Path("foo") 
public Foo getFoo() { return new Foo(...); } 

邮件正文作家被忽略,这工作得很好。

现在我想的是,也使用这个MessageBodyWriter,当我返回FooList<Bar>

我认为后者可以通过只写一个自定义MessageBodyWriterList情况下可以实现,但对于前一种情况我不能为包含Bar字段的所有应用程序类编写邮件正文编写器。

关于如何解决这个问题的任何想法?我还试图在Bar实例上使用Jackson序列化程序,但看起来它甚至没有被RestEasy注册(然后,我认为这种方式太脆弱了)。

回答

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实体提供者是而不是递归。也就是说,对于在资源方法中返回的给定对象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-mapperjackson-jaxrs罐(也可能是jackson-core之一)。

+0

感谢您的解释。可能痛点显然是非递归性。 我已经在考虑使用JacksonSerializer,但无论出于何种原因,由于我仍在调查的任何原因,RE没有注册。 至少我并不完全偏离轨道:) – 2013-03-05 19:08:03

+0

使用RestEasy,确保您实际上已经使用代码部署了Jackson库(除了resteasy-jackson提供程序库)。我假设你用'@JsonSerialize(using = MyCustomSerializer.class)'注释了你的bean。 – Perception 2013-03-05 19:11:10

+0

感知 - 有趣;会尝试。你知道是否有需要的最低版本的杰克逊库?是的,我以这种方式注释了他们。 – 2013-03-05 20:42:04

1

JAX-RS运行时将只为资源方法返回的对象查找一个MessageBodyWriter(参见本规范的第4.2.2节“消息正文编写器”部分),然后该单一MessageBodyWriter完全控制整个对象图将被返回给客户端。

为了实现您想要的行为,您需要每种媒体类型的自定义MessageBodyWriter,即在图形中遇到特定类型时,愿意将对象图的一部分的序列化委托给另一个写入器,然后恢复自己的逻辑。获取特定类型的代理编写器不会是一个大问题(注入javax.ws.rs.ext.Providers并呼吁getMessageBodyWriter()),但我不认为现有的xml/json/etc序列化器是在考虑这种类型的扩展的情况下实现的,所以我猜测你不能只传达他们。仅仅为此重新实现一个xml编码器也不是一个有吸引力的选项。

+0

至少我只寻找一个JSON这个自定义序列:-)感谢您指出该选项WRT代表团。 – 2013-03-05 19:10:34