使用Jersey 2.2和Jackson 2.1创建自定义ObjectMapper

52

我正在使用 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


你到底在苦恼什么? - Prmths
Jersey忽略了我的ObjectMapperResolver。我使用rc.register(ObjectMapperResolver.class);进行了注册,但是没有起作用。 - svenwltr
你的构造函数和getContext方法被调用了吗?为什么要加上这个注解:@Produces(MediaType.APPLICATION_JSON)?我会把它移除掉。 - MoD
构造函数和getContext都没有被调用。@Produces没有任何理由... - svenwltr
我们遇到了类似的问题,但是使用的是Jersey 1.13版本。对我们来说,我们需要使用org.codehaus.jackson.map.ObjectMapper而不是com.fasterxml.jackson.databind.ObjectMapper。我们从查看https://jersey.java.net/nonav/documentation/1.13/user-guide.html第5章的示例项目中找到了解决方法。 - David Weinberg
1
我通过这些指令解决了我的问题...使用Jackson、Jersey和Payara Micro进行REST Web服务...二级 - Wedson Quintanilha da Silva
8个回答

48
下面的解决方案适用于以下堆栈(即...这是我用来测试它的设置)
Jersey 2.12,Jackson 2.4.x
自从今天我进行了许多谷歌搜索以来,我正在添加我的消息和我想出的解决方案,因为它对我来说非常相关... 这是一个繁琐的解决方案,我认为这是一个更加繁琐的问题。
确保您的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. 创建一个@Provider组件,继承com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider,如下所示:

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 来包装控制器的响应。
  2. 请确保您仔细考虑(复制/粘贴)以下代码片段,因为唯一的“非强制性”部分是关于com.fasterxml.jackson.databind.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);
    }
}

  1. 无法编译 - 找不到符号“objectMapperAtRest”。这只是想要“mapper”吗?
- fragorl
我无法让它工作。出现了org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException错误:找不到媒体类型为application/json,类为<Some Bean>的MessageBodyWriter。 - fragorl
@fragorl 你是对的,“objectMapperAtRest”应该是“mapper”。 - Filip
@fragorl 请添加Maven依赖项 [jersey-media-json-jackson] (http://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson/2.21) - Filip
1
用 {{jackson-jaxrs-json-provider}} 替换 {{jersey-media-json-jackson}} 对我来说解决了这个问题... - snooze92
显示剩余3条评论

36

我找到了解决方案。我必须自己实例化Jackson提供程序并设置我的自定义ObjectMapper。一个可行的示例可以在GitHub上找到:https://github.com/svenwltr/example-grizzly-jersey-jackson/tree/stackoverflow-answer

我删除了我的ObjectMapperResolver并修改了我的main方法:

public class Main {
    public static void main(String[] args) {
        try {
            // create custom ObjectMapper
            ObjectMapper mapper = new ObjectMapper();
            mapper.enable(SerializationFeature.INDENT_OUTPUT);

            // create JsonProvider to provide custom ObjectMapper
            JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
            provider.setMapper(mapper);

            // configure REST service
            ResourceConfig rc = new ResourceConfig();
            rc.register(ExampleResource.class);
            rc.register(provider);

            // create Grizzly instance and add handler
            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, "/");

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

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

6
这非常有帮助,但仍存在问题:Jersey会自动发现Jackson provider,因此它会创建一个(可能未配置的)provider,然后这段代码显式地注册了一个(正确配置的)provider,因此Jersey最终会有两个providers。我在(https://github.com/svenwltr/example-grizzly-jersey-jackson/issues/1)上进行了说明。我不知道如何解决这个问题。有什么想法吗? - Michael Iles
我相信你可以关闭自动发现,但这样你就会失去它的所有功能。 - Giovanni Botta
给定的示例对我有效。同时,请尝试使用user915662s的解决方案。 - svenwltr
这对我来说很有效,当我尝试使用protos运行一些测试用例时。不错! - Lorcan O'Neill
您可以使用 resourceConfig.addProperties(Collections.singletonMap(CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true)) 来禁用自动发现功能。 - jediz
我不需要明确引用 ObjectMapperContext。只需确保您将其放在一个包下,例如 com.yourcompany.a.b.c,然后确保您在您的 ResourceConfig(或主类)中有这个指令:packages("com.yourcompany.a.b.c"); - Clint Eastwood

9

我通过一些试验解决了这个问题。

问题似乎出在Jersey的特征自动检测机制上。如果你依赖Jersey来加载JacksonJaxbJsonProvider,那么ObjectMapper的自定义上下文提供程序将被忽略。相反,如果你手动注册功能,它就会起作用。我假设这与自动检测的提供程序被加载到不同的上下文范围有关,但至于解决方案,以下是我最终得出的结论。请注意,我将其包装成一个功能,你应该能够直接向你的应用程序注册它而没有任何问题。

public final class RequestMappingFeature implements Feature {

    @Override
    public boolean configure(final FeatureContext context) {

        context.register(ObjectMapperProvider.class);

        // If you comment out this line, it stops working.
        context.register(JacksonJaxbJsonProvider.class);

        return true;
    }
}

2017年11月更新:Jersey2的情况有所改变。如果以上方法无效,请尝试以下方法:

现在提供自己的ObjectMapper的新方法如下:

public final class JacksonFeature implements Feature {

    private static final ObjectMapper MAPPER;

    static {

        // Create the new object mapper.
        MAPPER = new ObjectMapper();

        // Enable/disable various configuration flags.
        MAPPER.configure(
                DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);

        // ... Add your own configurations here.

    }
    @Override
    public boolean configure(final FeatureContext context) {
        JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider(
                MAPPER, DEFAULT_ANNOTATIONS);
        context.register(provider);

        return true;
    }
}

添加此功能只会给我带来“警告:未找到资源类的资源方法...RequestMappingFeature”。 - Alkanshel
1
“new method” 在 Jersey 2.27 和 Jackson 2.9 上对我有效。 - Hank
适用于 Jersey 2.23.2 和 Jackson 2.5.4,比其他解决方案简单得多。为了使下次使用变得非常简单,DEFAULT_ANNOTATIONSJacksonJaxbJsonProvider 上的一个字段,您需要 ResourceConfig.register(JacksonFeature.class) 注册它。 - elhefe

8
请按照以下步骤操作:

1)添加pom.xml依赖

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

2) 在Main.java中注册JacksonFeature

public class Main {

    public static void main(String[] args) {
        try {
            ResourceConfig rc = new ResourceConfig();
            rc.register(ExampleResource.class);
            rc.register(ObjectMapperResolver.class);
            rc.register(JacksonFeature.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);
        }
    }
}

3) 在您的资源中使用 org.codehaus.jackson.map.ObjectMapper

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

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig.Feature;

@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(Feature.INDENT_OUTPUT);
    }

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

3
可以工作,但我必须降级到Jackson 1.9。我更喜欢Jackson 2.1。抱歉,我没有提到这点。 - svenwltr
对于我们这些最近才接触到这个问题的人来说 - 它仍然存在于最新的Jackson 2.x(v2.3)中。此答案使用较旧的Jersey / Jackson连接器库,该库依赖于Jackson 1.x。整个问题在于,在Jackson 1.x中有效的内容在2.x中不起作用。目前必须手动注册Jackson提供程序(关闭METAINF自动发现)。 - mujimu
4
我不明白为什么这个类上有一个@Produces注释。这不是Jersey资源..! - GuiSim

7
从Jersey 2.17文档中: https://eclipse-ee4j.github.io/jersey.github.io/documentation/2.17/media.html#jackson-registration 在应用程序中,
@ApplicationPath("/")
public class MyApplication extends ResourceConfig {
  public MyApplication() {
    register(JacksonFeature.class);
    // This is the class that you supply, Call it what you want
    register(JacksonObjectMapperProvider.class);
    //...
  }
}

修改,忘了添加在register(..)中提供的JacksonObjectMapperProvider:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
public class JacksonObjectMapperProvider implements ContextResolver<ObjectMapper>{
  final ObjectMapper defaultObjectMapper;

  public JacksonObjectMapperProvider() {
     defaultObjectMapper = createDefaultMapper();
  }

  @Override
  public ObjectMapper getContext(Class<?> type) {return defaultObjectMapper;}

   public static ObjectMapper createDefaultMapper() {
      final ObjectMapper jackson = new ObjectMapper();
      // any changes to the ObjectMapper is up to you. Do what you like.
      // The ParameterNamesModule is optional,
      // it enables you to have immutable POJOs in java8
      jackson.registerModule(new ParameterNamesModule());
      jackson.enable(SerializationFeature.INDENT_OUTPUT);
      jackson.disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS);
      jackson.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
      return jackson;
   }
}

1
这不是问题的答案。我认为你错过了他试图注册一个自定义映射器,而不是默认映射器的重点。 - Zero3
它有效。new ParameterNamesModule() 对象中有什么? - sytolk
createDefaultMapper() 方法提供了自定义的 Objectmapper。在该方法中创建任何 ObjectMapper 并配置它以按您希望的方式工作。ParameterNamesModule (https://github.com/FasterXML/jackson-modules-java8/tree/master/parameter-names) 只是您可以配置的示例。 - George

7

由于我在使用Java EE7和Glassfish4时花费了数小时才使其正常工作,所以这是我的解决方案:

@javax.ws.rs.ApplicationPath("withJackson")
public class ApplicationConfig extends Application {

    private static final Logger log = java.util.logging.Logger.getLogger(ApplicationConfig.class.getName());

    @Override
    public Set<Object> getSingletons() {
        Set<Object> set = new HashSet<>();
        log.log(Level.INFO, "Enabling custom Jackson JSON provider");
        set.add(new JacksonJsonProvider().configure(SerializationFeature.INDENT_OUTPUT, true));
        return set;
    }

    @Override
    public Map<String, Object> getProperties() {
        Map<String, Object> map = new HashMap<>();
        log.log(Level.INFO, "Disabling MOXy JSON provider");
        map.put("jersey.config.disableMoxyJson.server", true);
        return map;
    }

    @Override
public Set<Class<?>> getClasses() {
    Set<Class<?>> resources = new java.util.HashSet<>();
    addRestResourceClasses(resources);
    return resources;
}

/**
 * Do not modify addRestResourceClasses() method.
 * It is automatically populated with
 * all resources defined in the project.
 * If required, comment out calling this method in getClasses().
 */
private void addRestResourceClasses(Set<Class<?>> resources) {
    resources.add(com.fasterxml.jackson.jaxrs.base.JsonMappingExceptionMapper.class);
    resources.add(com.fasterxml.jackson.jaxrs.base.JsonParseExceptionMapper.class);
    resources.add(com.fasterxml.jackson.jaxrs.json.JsonMappingExceptionMapper.class);
    resources.add(com.fasterxml.jackson.jaxrs.json.JsonParseExceptionMapper.class);
    resources.add(de.lathspell.java_test_ee7_json.Api.class);
    resources.add(de.lathspell.java_test_ee7_json.with_jackson.MyExceptionMapper.class);
}

唯一相关的POM依赖项是:

    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>2.2.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.2.3</version>
    </dependency>

    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>

+1 对于 map.put("jersey.config.disableMoxyJson.server", true);,它让我苦苦挣扎了数小时。谢谢! - Montri M
谢谢,这对我有用(SDK8,Jersey 2.10.x)。只是一个备注,如果第一次没有添加Moxy,则无需禁用它。 - timmz

2

在Jackson 2.7中,制作这个并不起作用:

public class MyApplication extends ResourceConfig {
    public MyApplication() {
    register(MyObjectMapperProvider.class);
}}

MyObjectMapperProvider构造函数被调用,但是getContext()从未被调用

在super()构造函数中注册MyObjectMapperProvider可以使其正常工作:

public class MyApplication extends ResourceConfig {
   public MyApplication() {
       super(
            // register Jackson ObjectMapper resolver
            MyObjectMapperProvider.class
       );
}}

看看这个Jersey示例代码

0
如果你正在寻找Jersey 3+的解决方案,你需要为Jackson引入Jakarta Provider依赖。正如Filip在他的回答中所说,请注意你只有一个json提供者,即jaxrs提供者在你的依赖中。(确保你的pom.xml中没有包含"jersey-media-json-jackson"提供者。)
   <dependency>
     <groupId>com.fasterxml.jackson.jakarta.rs</groupId>
     <artifactId>jackson-jakarta-rs-json-provider</artifactId>
   </dependency>

根据krotscheck的代码示例,您现在可以为Jersey3+创建一个JacksonFeature。
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.jakarta.rs.json.JacksonXmlBindJsonProvider;

import jakarta.ws.rs.core.Feature;
import jakarta.ws.rs.core.FeatureContext;

public final class JacksonFeature implements Feature {

    private static final ObjectMapper MAPPER = new ObjectMapper()
            .configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true)
            .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    @Override
    public boolean configure(final FeatureContext context) {
        JacksonXmlBindJsonProvider provider = new JacksonXmlBindJsonProvider(MAPPER,
                JacksonXmlBindJsonProvider.DEFAULT_ANNOTATIONS);
        context.register(provider);

        return true;
    }
}

在客户端中注册此功能。
Client client = ClientBuilder.newClient().register(JacksonFeature.class)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接