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

时间:2018-11-07 17:55:04

标签: jackson micronaut

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

2 个答案:

答案 0 :(得分:2)

Micronaut使用ObjectMapperFactory来构造ObjectMapper,该Micronaut Framework Twitter account不会设置属性命名策略(至少在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;
        }
    }
}

在此示例中,我向主CustomObjectMapperFactory类添加了静态类Application,并且使用了@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<ObjectMapper>

还有一种实现相同效果的替代方法,它需要更少的代码行数。学分归:)

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

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)。

答案 1 :(得分:1)

此问题在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)
    }