如何在jersey2 / hk2应用程序中获取Jackson Object Mapper的引用 [英] How do I get a reference to the Jackson Object Mapper in a jersey2 / hk2 application
问题描述
我有一个jersey2应用程序,通过Jackson配置为JSON支持,添加
I have a jersey2 application configured for JSON support via Jackson, adding
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
public MyApplication() {
...
register(JacksonFeature.class)
...
}
。一切正常,我的资源将反序列化的POJO作为参数
in my application. Everything works, my resources get deserialized POJOs as arguments
@POST @Consumes(MediaType.APPLICATION_JSON)
public void blah(MyPojo p) {
...
}
现在其中一个资源需要引用Jackson的 ObjectMapper
来自行进行反序列化。我尝试过这样的事情
Now one of thoese resources needs a reference to Jackson's ObjectMapper
to do some deserialization on its own. I've tried doing something like
@Inject
public MyResource(@Context ObjectMapper mapper) {
...
}
或
@GET
public String foo(@Context ObjectMapper mapper) {
...
}
但在这两种情况下,对 mapper
的引用都为空。如何在我的资源中注入对 ObjectMapper
的引用?
but in both cases the reference to mapper
is null. How can I inject a reference to the ObjectMapper
in my resources?
推荐答案
首先,杰克逊提供商没有使用默认的 ObjectMapper
。它实际上根本不使用 ObjectMapper
。它利用其他Jackson API来处理(反)序列化。
First there is no default ObjectMapper
used by the Jackson provider. It doesn't use an ObjectMapper
at all actually. It makes use of other Jackson APIs to handle the (de)serialization.
如果你想使用/注入一个 ObjectMapper
实例,那么你应该为它创建一个 Factory
If you want to use/inject a single ObjectMapper
instance, then you should just create a Factory
for it
public class ObjectMapperFactory implements Factory<ObjectMapper> {
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的任何配置
非线程安全。所以说你试图从你的资源方法配置它,那些操作不是线程安全的。
One thing should be noted is that any configuration of the ObjectMapper
is not thread safe. So say you tried to configure it from your resource method, those operations are not thread safe.
杰克逊提供商需要注意的另一件事是,如果我们提供一个 ContextResolver
,如@Laurentiu L 提到的,杰克逊提供商将会切换到使用我们的 ObjectMapper
。在这种情况下,如果你想使用相同的 ObjectMapper
,那么你可以在 Factory
中查找。例如
Another thing to note with the Jackson provider, is that if we provide a ContextResolver
, like mentioned by @Laurentiu L, then the Jackson provider will switch to using our ObjectMapper
. In which case, if you want to use that same ObjectMapper
, then you can look it up in the Factory
. For example
public class ObjectMapperFactory implements Factory<ObjectMapper> {
private final Providers providers;
final ObjectMapper mapper = new ObjectMapper();
public ObjectMapperFactory(@Context Providers providers) {
this.providers = providers;
}
@Override
public ObjectMapper provide() {
ContextResolver<ObjectMapper> 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< ObjectMapper>
,并确保使用相应的 @Produces
ContextResolver >和 @Consumes
媒体类型。
For the above to work (use a single ObjectMapper
), you need to make sure to implement the ContextResolver<ObjectMapper>
, and make sure to annotation the ContextResolver
with the corresponding @Produces
and @Consumes
media types.
这篇关于如何在jersey2 / hk2应用程序中获取Jackson Object Mapper的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!