如何配置 Jackson 在 Micronaut 中使用 SNAKE_CASE?
How to configure Jackson to use SNAKE_CASE in Micronaut?
我尝试将 jackson 配置为在使用 Micronaut 时使用 SNAKE_CASE 接受 JSON,但是,它无法识别 属性 jackson.property-naming-strategy: SNAKE_CASE
。
来自 Micronaut 1.1.1
application.yml
jackson:
property-naming-strategy: SNAKE_CASE
Micronaut 1.1.1 之前
Micronaut 使用未设置 属性 命名策略的 ObjectMapperFactory
构造 ObjectMapper
(至少在 Micronaut 1.0 GA 版本中,这可能会在未来的版本中更改)。配置 class 不支持您在问题中提到的配置选项,因此使用它根本没有任何作用。但是,您可以将 ObjectMapperFactory
class 替换为您自己的自定义实现,该实现以默认方式构造 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
class 中添加了一个静态 class CustomObjectMapperFactory
并且我使用了 @Replaces
注释来指示 Micronaut使用此自定义工厂 class 提供的工厂 class 和 objectMapper()
方法。我们 return 来自该工厂的 ObjectMapper
实例基于默认工厂方法 + 它添加了:
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
设置预期的 属性 命名策略。
这是我在添加此自定义工厂后在响应中返回的示例输出 class:
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"
}
默认情况下(没有这个自定义工厂 class)响应如下所示:
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>
有另一种方法可以达到相同的效果,需要的代码行数更少。学分转到 Micronaut Framework Twitter account :)
我们可以使用 BeanCreatedEventListener<T>
来响应 bean 创建事件并允许我们扩展刚刚创建的 bean。在这种情况下,它意味着添加一个 class 实现 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)。
此问题已从 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 接受 JSON,但是,它无法识别 属性 jackson.property-naming-strategy: SNAKE_CASE
。
来自 Micronaut 1.1.1
application.yml
jackson:
property-naming-strategy: SNAKE_CASE
Micronaut 1.1.1 之前
Micronaut 使用未设置 属性 命名策略的 ObjectMapperFactory
构造 ObjectMapper
(至少在 Micronaut 1.0 GA 版本中,这可能会在未来的版本中更改)。配置 class 不支持您在问题中提到的配置选项,因此使用它根本没有任何作用。但是,您可以将 ObjectMapperFactory
class 替换为您自己的自定义实现,该实现以默认方式构造 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
class 中添加了一个静态 class CustomObjectMapperFactory
并且我使用了 @Replaces
注释来指示 Micronaut使用此自定义工厂 class 提供的工厂 class 和 objectMapper()
方法。我们 return 来自该工厂的 ObjectMapper
实例基于默认工厂方法 + 它添加了:
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
设置预期的 属性 命名策略。
这是我在添加此自定义工厂后在响应中返回的示例输出 class:
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"
}
默认情况下(没有这个自定义工厂 class)响应如下所示:
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>
有另一种方法可以达到相同的效果,需要的代码行数更少。学分转到 Micronaut Framework Twitter account :)
我们可以使用 BeanCreatedEventListener<T>
来响应 bean 创建事件并允许我们扩展刚刚创建的 bean。在这种情况下,它意味着添加一个 class 实现 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)。
此问题已从 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)
}