如何使用 Jackson 全局定义命名约定
Posted
技术标签:
【中文标题】如何使用 Jackson 全局定义命名约定【英文标题】:how to globally define the naming convention with Jackson 【发布时间】:2016-12-23 16:45:41 【问题描述】:我在 Spring 中使用 Jackson。我有一些这样的方法:
@RequestMapping(value = "/myURL", method = RequestMethod.GET)
public @ResponseBody Foo getFoo()
// get foo
return foo;
被序列化的类 Foo 很大并且有很多成员。序列化没问题,使用注解或者自定义序列化器。
我唯一想不通的是如何定义命名约定。我想对所有序列化使用snake_case。
那么如何全局定义序列化的命名约定?
如果不可能,则必须使用本地解决方案。
【问题讨论】:
【参考方案1】:不确定如何在全局范围内执行此操作,但这是一种在 JSON 对象级别而不是针对每个单独属性的方法:
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class Foo
private String myBeanName;
//...
将产生 json:
"my_bean_name": "Sth"
//...
【讨论】:
我尝试了这种方法,但收到一个错误:-- HttpMessageNotWritableException:无法写入内容:类型 com.fasterxml.jackson.databind.PropertyNamingStrategy$SnakeCaseStrategy 不存在(通过引用链:java.util.数组列表[0]); -- 这可能是因为我返回 List其实有一个很简单的答案:
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder()
Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
b.propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
return b;
我将它添加到我的主目录中,如下所示:
@SpringBootApplication
public class Application
public static void main(String [] args)
SpringApplication.run(Application.class, args);
@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder()
Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
b.propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
return b;
【讨论】:
CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES 自 2.7 起已弃用,请改用 SNAKE_CASE。【参考方案3】:映射器有一个用于PropertyNamingStrategy的setter(用于设置自定义属性命名策略的方法。)
在 tes 示例中看看它是如何工作的:
@Test
public void namingStrategy() throws Exception
final ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PropertyNamingStrategyBase()
@Override
public String translate(String s)
return s.toUpperCase();
);
final String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(new SomePojo("uuid_1", "user_1", "Bruce", "W.", 51));
System.out.println(json);
public static class SomePojo
private String someIdAttachedToIt;
private String username;
private String fistName;
private String lastName;
private int age;
public SomePojo(String someIdAttachedToIt, String username, String fistName, String lastName, int age)
this.someIdAttachedToIt = someIdAttachedToIt;
this.username = username;
this.fistName = fistName;
this.lastName = lastName;
this.age = age;
public String getSomeIdAttachedToIt()
return someIdAttachedToIt;
public String getUsername()
return username;
public String getFistName()
return fistName;
public String getLastName()
return lastName;
public int getAge()
return age;
输出:
"SOMEIDATTACHEDTOIT" : "uuid_1",
"USERNAME" : "user_1",
"FISTNAME" : "Bruce",
"LASTNAME" : "W.",
"AGE" : 51
提供的策略(我使用 LOWERCASE 作为示例)
PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
PropertyNamingStrategy.SNAKE_CASE
要在 Spring 中全局添加策略,您至少可以通过以下两种方式进行:
将映射器模块声明为包含命名策略的 bean 根据需要配置自定义对象映射器短版:
@Configuration
public static class Config
@Bean
public Module module()
return new SimpleModule()
@Override
protected SimpleModule setNamingStrategy(PropertyNamingStrategy naming)
super.setNamingStrategy(new PropertyNamingStrategy.PropertyNamingStrategyBase()
@Override
public String translate(String propertyName)
// example: "propertyName" -> "PROPERTYNAME"
return propertyName.toUpperCase();
);
return this;
;
加长版:
为jackson模块声明bean:
// config auto scan by spring
@Configuration
public static class ConfigurationClass
// declare the module as a bean
@Bean
public Module myJsonModule()
return new MySimpleModule();
// jackson mapper module to customize mapping
private static class MySimpleModule extends SimpleModule
@Override
protected SimpleModule setNamingStrategy(PropertyNamingStrategy naming)
return super.setNamingStrategy(new MyNameStrategy());
// your naming strategy
private static class MyNameStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase
@Override
public String translate(String propertyName)
return propertyName.toUpperCase();
您也可以在 xml 中声明 bean。
它不会覆盖明确定义道具名称的@JsonProperty。
【讨论】:
我应该对 Confid 类做些什么吗?把它挂在某个地方? 是的,只需在 Spring 可以在启动时自动扫描的包中创建它。它只是持有bean声明。您也可以使用 xml 配置创建它(需要创建自己的 SimpleModule 扩展类)。以上是关于如何使用 Jackson 全局定义命名约定的主要内容,如果未能解决你的问题,请参考以下文章
将JSON转换为Java Object,如何使用Jackson解析BadgerFish约定