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

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

【问题讨论】:

    标签: jackson micronaut


    【解决方案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)
        }
    

    【讨论】:

      猜你喜欢
      • 2017-11-18
      • 1970-01-01
      • 1970-01-01
      • 2015-04-03
      • 2020-11-04
      • 1970-01-01
      • 2021-05-19
      • 2021-03-01
      • 2019-02-20
      相关资源
      最近更新 更多