字段的特定MessageBodyWriter

时间:2013-03-05 17:22:44

标签: java jackson jax-rs resteasy

假设我在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注册(然后,我认为这种方式太脆弱了。)

3 个答案:

答案 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-mapperjackson-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