gpt4 book ai didi

java - 带有 Jersey 2.2 和 Jackson 2.1 的自定义 ObjectMapper

转载 作者:IT老高 更新时间:2023-10-28 20:39:39 26 4
gpt4 key购买 nike

我正在努力使用 Grizzly、Jersey 和 Jackson 的 REST 应用程序,因为 Jersey 忽略了我的自定义 ObjectMapper。

POM 依赖:

<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-servlet</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.1.4</version>
</dependency>
</dependencies>

产生的版本是:Grizzly 2.3.3、Jackson 2.1.4 和 Jersey 2.2。

主类(我想要显式注册 Jersey 组件):

public class Main {
public static void main(String[] args) {
try {
ResourceConfig rc = new ResourceConfig();
rc.register(ExampleResource.class);
rc.register(ObjectMapperResolver.class);

HttpHandler handler = ContainerFactory.createContainer(
GrizzlyHttpContainer.class, rc);

URI uri = new URI("http://0.0.0.0:8080/");

HttpServer server = GrizzlyHttpServerFactory.createHttpServer(uri);

ServerConfiguration config = server.getServerConfiguration();
config.addHttpHandler(handler, "/");

server.start();
System.in.read();

} catch (ProcessingException | URISyntaxException | IOException e) {
throw new Error("Unable to create HTTP server.", e);
}
}
}

ObjectMapper 的上下文解析器:

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class ObjectMapperResolver implements ContextResolver<ObjectMapper> {

private final ObjectMapper mapper;

public ObjectMapperResolver() {
System.out.println("new ObjectMapperResolver()");
mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
}

@Override
public ObjectMapper getContext(Class<?> type) {
System.out.println("ObjectMapperResolver.getContext(...)");
return mapper;
}

}

ObjectMapperResolver 构造函数和 getContext 都没有被调用。我错过了什么?我更喜欢使用 Jersey 2.2 和 Jackson 2.1,因为它是另一个库的依赖项。

可以在 GitHub 上找到完整示例:https://github.com/svenwltr/example-grizzly-jersey-jackson/tree/stackoverflow

最佳答案

以下解决方案适用于以下堆栈(如...这是我用来测试它的设置)

泽西 2.12, jackson 2.4.x

我将我的消息与我在这篇文章中提出的解决方案一起添加,因为它与我今天输入的许多 Google 搜索非常相关......对于我所相信的而言,这是一个繁琐的解决方案成为一个更麻烦的问题。

1。确保您的 Maven 配置包含 jackson-jaxrs-json-provider 依赖项:

<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.1</version>
</dependency>

2。确保您的 Maven 配置不包含 jersey-media-json-jackson 依赖项:

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>

3。创建一个扩展 com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider@Provider 组件,如下所示:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class CustomJsonProvider extends JacksonJaxbJsonProvider {

private static ObjectMapper mapper = new ObjectMapper();

static {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
}

public CustomJsonProvider() {
super();
setMapper(mapper);
}
}

如您所见,这也是我们定义 com.fasterxml.jackson.databind.ObjectMapper

的自定义实例的地方

4。通过 MarshallingFeature 扩展 javax.ws.rs.core.Feature,如下所示:

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;

public class MarshallingFeature implements Feature {

@Override
public boolean configure(FeatureContext context) {
context.register(CustomJsonProvider.class, MessageBodyReader.class, MessageBodyWriter.class);
return true;
}
}

5。您需要像这样注册此自定义提供程序,前提是您通过 org.glassfish.jersey.server.ResourceConfig 像这样配置您的应用程序:

import org.glassfish.jersey.server.ResourceConfig;
...

public class MyApplication extends ResourceConfig {

public MyApplication() {

...
register(MarshallingFeature.class);
...
}
}

其他说明和意见:

  1. 无论您是否使用 javax.ws.rs.core.Response 来包装 Controller 的响应,此解决方案都适用。
  2. 请确保您仔细考虑(复制/粘贴)以下代码片段,因为唯一的“非强制性”可以说是与 com.fasterxml.jackson 的自定义配置有关的部分。数据绑定(bind).ObjectMapper.

@jcreason

很抱歉,@jcreason 把球丢在了这个上面,我希望你仍然是古玩。所以我检查了去年的代码,这就是我想出的提供自定义映射器的方法。

问题在于,在功能初始化期间,任何自定义对象映射器都会被

中的某些代码禁用

org.glassfish.jersey.jackson.JacksonFeature:77 (jersey-media-json-jackson-2.12.jar)

// Disable other JSON providers.
context.property(PropertiesHelper.getPropertyNameForRuntime(InternalProperties.JSON_FEATURE, config.getRuntimeType()), JSON_FEATURE);

但是这个特性只能被这个组件注册

org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable

if (!context.getConfiguration().isRegistered(JacksonFeature.class)) {
context.register(JacksonFeature.class);
}

所以我所做的是注册我自己的功能,该功能注册我自己的对象映射器提供程序并放入绊线停止org.glassfish.jersey.jackson.JacksonFeature 被注册并覆盖我的对象映射器......

import com.fasterxml.jackson.jaxrs.base.JsonMappingExceptionMapper;
import com.fasterxml.jackson.jaxrs.base.JsonParseExceptionMapper;

import org.glassfish.jersey.internal.InternalProperties;
import org.glassfish.jersey.internal.util.PropertiesHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;

public class MarshallingFeature implements Feature {

private final static String JSON_FEATURE = MarshallingFeature.class.getSimpleName();

@Override
public boolean configure(FeatureContext context) {

context.register(JsonParseExceptionMapper.class);
context.register(JsonMappingExceptionMapper.class);
context.register(JacksonJsonProviderAtRest.class, MessageBodyReader.class, MessageBodyWriter.class);

final Configuration config = context.getConfiguration();
// Disables discoverability of org.glassfish.jersey.jackson.JacksonFeature
context.property(
PropertiesHelper.getPropertyNameForRuntime(InternalProperties.JSON_FEATURE,
config.getRuntimeType()), JSON_FEATURE);

return true;
}
}

这是自定义对象映射器提供程序...

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonJsonProviderAtRest extends JacksonJaxbJsonProvider {

private static ObjectMapper objectMapperAtRest = new ObjectMapper();

static {
objectMapperAtRest.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapperAtRest.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapperAtRest.configure(SerializationFeature.INDENT_OUTPUT, true); // Different from default so you can test it :)
objectMapperAtRest.setSerializationInclusion(JsonInclude.Include.ALWAYS);
}

public JacksonJsonProviderAtRest() {
super();
setMapper(objectMapperAtRest);
}
}

关于java - 带有 Jersey 2.2 和 Jackson 2.1 的自定义 ObjectMapper,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18872931/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com