如何配置 Jackson 在 Micronaut 中使用 SNAKE_CASE?

Posted

技术标签:

【中文标题】如何配置 Jackson 在 Micronaut 中使用 SNAKE_CASE?【英文标题】:How to configure Jackson to use SNAKE_CASE in Micronaut? 【发布时间】:2019-04-11 05:07:50 【问题描述】:

我尝试将 jackson 配置为在使用 Micronaut 时使用 SNAKE_CASE 接受 JSON,但是它无法识别属性 jackson.property-naming-strategy: SNAKE_CASE

【问题讨论】:

【参考方案1】:

来自 Micronaut 1.1.1

application.yml

jackson:
    property-naming-strategy: SNAKE_CASE

在 Micronaut 1.1.1 之前

Micronaut 使用不设置属性命名策略的 ObjectMapperFactory 构造 ObjectMapper(至少在 Micronaut 1.0 GA 版本中,这可能会在未来的版本中改变)。配置类不支持您在问题中提到的配置选项,因此使用它根本没有任何作用。但是,您可以将ObjectMapperFactory 类替换为您自己的自定义实现,该实现以默认方式构造ObjectMapper + 它设置属性命名策略。考虑以下示例:

package com.github.wololock.micronaut;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Replaces;
import io.micronaut.jackson.JacksonConfiguration;
import io.micronaut.jackson.ObjectMapperFactory;
import io.micronaut.runtime.Micronaut;

import javax.inject.Singleton;
import java.util.Optional;

public class Application 

    public static void main(String[] args) 
        Micronaut.run(Application.class);
    

    @Factory
    @Replaces(ObjectMapperFactory.class)
    static class CustomObjectMapperFactory extends ObjectMapperFactory 

        @Override
        @Singleton
        @Replaces(ObjectMapper.class)
        public ObjectMapper objectMapper(Optional<JacksonConfiguration> jacksonConfiguration, Optional<JsonFactory> jsonFactory) 
            final ObjectMapper mapper = super.objectMapper(jacksonConfiguration, jsonFactory);
            mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
            return mapper;
        
    

在这个例子中,我在主Application 类中添加了一个静态类CustomObjectMapperFactory,并使用@Replaces 注释来指示Micronaut 使用这个工厂类和这个自定义工厂类提供的objectMapper() 方法。我们从这个工厂返回的ObjectMapper 实例是基于默认工厂方法+它添加的:

mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

设置预期的属性命名策略。

这是添加此自定义工厂类后我在响应中返回的示例输出:

HTTP/1.1 200 OK
Date: Wed, 7 Nov 2018 19:15:10 GMT
connection: keep-alive
content-length: 38
content-type: application/json


    "first_name": "Joe",
    "last_name": "Doe"

默认情况下(没有此自定义工厂类)响应如下所示:

HTTP/1.1 200 OK
Date: Wed, 7 Nov 2018 19:04:14 GMT
connection: keep-alive
content-length: 36
content-type: application/json


    "firstName": "Joe",
    "lastName": "Doe"


更新:改用BeanCreatedEventListener&lt;ObjectMapper&gt;

还有一种替代方法可以实现同样的效果,只需要更少的代码行。致谢Micronaut Framework Twitter account :)

我们可以使用BeanCreatedEventListener&lt;T&gt; 来响应 bean 创建事件并允许我们扩展刚刚创建的 bean。在这种情况下,这意味着添加一个实现BeanCreatedEventListener&lt;ObjectMapper&gt; 并设置属性命名策略的类:

package com.github.wololock.micronaut;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import io.micronaut.context.event.BeanCreatedEvent;
import io.micronaut.context.event.BeanCreatedEventListener;
import io.micronaut.runtime.Micronaut;

import javax.inject.Singleton;

public class Application 

    public static void main(String[] args) 
        Micronaut.run(Application.class);
    

    @Singleton
    static class ObjectMapperBeanEventListener implements BeanCreatedEventListener<ObjectMapper> 

        @Override
        public ObjectMapper onCreated(BeanCreatedEvent<ObjectMapper> event) 
            final ObjectMapper mapper = event.getBean();
            mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
            return mapper;
        
    

此解决方案的优点:

更少的代码行数 少了一个抽象层(我们不必为ObjectMapperFactory操心,我们只关心配置现有的ObjectMapper bean)。

【讨论】:

不错!我尝试使用BeanInitializedEventListener 来完成相同的操作,但尚未选择钩子。它也应该有效吗? 是否还需要做其他事情才能使用BeanCreatedEventListener&lt;ObjectMapper&gt; 方法?到目前为止,它还没有......不确定我错过了什么 O:) 对 BeanCreatedEventListener 有帮助吗?在我的情况下,它进入 onCreated 方法,但对 objectmapper 没有影响。我正在尝试设置 mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);和 mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);。任何帮助将不胜感激。【参考方案2】:

此问题自 Micronaut 1.1.1 起已修复:https://github.com/micronaut-projects/micronaut-core/issues/1599

将此添加到您的 application.yml

jackson:
    property-naming-strategy: SNAKE_CASE

您可以使用以下方法对其进行测试:

    @Test
    fun testJackson() 
        val applicationContext = ApplicationContext.run()

        assertThat(applicationContext.getBean(JacksonConfiguration::class.java).propertyNamingStrategy).isEqualTo(PropertyNamingStrategy.SNAKE_CASE)
    

【讨论】:

以上是关于如何配置 Jackson 在 Micronaut 中使用 SNAKE_CASE?的主要内容,如果未能解决你的问题,请参考以下文章

在 micronaut 中为集成测试配置数据库

Micronaut 数据:没有为存储库配置支持 RepositoryOperations

Micronaut 环境和 logback 配置文件

Micronaut 配置未发出 JWT 刷新令牌

Micronaut微服务 实战入门

如何设置 Micronaut 上下文路径