如何在jersey2 / hk2应用程序中获取Jackson Object Mapper的引用

我有一个jersey2应用程序配置为通过jackson支持JSON,添加

 org.glassfish.jersey.media jersey-media-json-jackson ${jersey.version}  

在POM文件中

 public MyApplication() { ... register(JacksonFeature.class) ... } 

在我的申请中。 一切正常,我的资源将反序列化的POJO作为参数

 @POST @Consumes(MediaType.APPLICATION_JSON) public void blah(MyPojo p) { ... } 

现在,其中一个资源需要引用Jackson的ObjectMapper来自行进行反序列化。 我尝试过这样的事情

 @Inject public MyResource(@Context ObjectMapper mapper) { ... } 

要么

 @GET public String foo(@Context ObjectMapper mapper) { ... } 

但在这两种情况下,对mapper的引用都为null。 如何在我的资源中注入对ObjectMapper的引用?

首先,Jackson提供商没有使用默认的ObjectMapper 。 它实际上根本不使用ObjectMapper 。 它利用其他Jackson API来处理(反)序列化。

如果你想使用/注入一个ObjectMapper实例,那么你应该为它创建一个Factory

 public class ObjectMapperFactory implements Factory { final ObjectMapper mapper = new ObjectMapper(); @Override public ObjectMapper provide() { return mapper; } @Override public void dispose(ObjectMapper t) {} } 

然后绑定它

 register(new AbstractBinder(){ @Override public void configure() { bindFactory(ObjectMapperFactory.class) .to(ObjectMapper.class).in(Singleton.class); } }); 

需要注意的一点是, ObjectMapper任何配置都不线程安全的 。 所以说你试图从资源方法配置它,这些操作不是线程安全的。

jackson提供者需要注意的另一件事是,如果我们提供一个ContextResolver ,就像@Laurentiu L所提到的那样 ,那么Jackson提供者将转而使用我们的ObjectMapper 。 在这种情况下,如果您想使用相同的ObjectMapper ,那么您可以在Factory查找它。 例如

 public class ObjectMapperFactory implements Factory { private final Providers providers; final ObjectMapper mapper = new ObjectMapper(); public ObjectMapperFactory(@Context Providers providers) { this.providers = providers; } @Override public ObjectMapper provide() { ContextResolver resolver = providers.getContextResolver( ObjectMapper.class, MediaType.APPLICATION_JSON); if (resolver == null) { return mapper; } return resolver.getContext(null); } @Override public void dispose(ObjectMapper t) {} } 

为了使上述工作(使用单个ObjectMapper ),您需要确保实现ContextResolver ,并确保使用相应的@Produces@Consumes媒体类型注释@Consumes

除了JacksonFeature之外,您还需要为ObjectMapper注册ContextResolver。

9.1.4.2中的文档中的简单示例。 配置并注册

 @Provider public class MyObjectMapperProvider implements ContextResolver { final ObjectMapper defaultObjectMapper; public MyObjectMapperProvider() { defaultObjectMapper = createDefaultMapper(); } @Override public ObjectMapper getContext(Class type) { return defaultObjectMapper; } private static ObjectMapper createDefaultMapper() { final ObjectMapper result = new ObjectMapper(); result.configure(Feature.INDENT_OUTPUT, true); return result; } // ... } 

Github上提供了完整的代码示例

您还需要注册它

  .register(MyObjectMapperProvider.class)