杰克逊放弃下划线,转而使用驼峰命名法

215

我从互联网检索到一个JSON字符串;就像我所看到的大多数JSON一样,其中包括由下划线分隔的长键。我的目标基本上是将JSON反序列化为Java对象,但我在Java代码中不使用下划线。

例如,我可能有一个User类,其中firstName字段使用驼峰式命名,同时我需要告诉Jackson将JSON中的first_name键映射到firstName类字段。这可行吗?

class User{
    protected String firstName;
    protected String getFirstName(){return firstName;}
}
11个回答

474

Jackson 2.12+ 中,你可以配置 ObjectMapper 将驼峰式命名转换为带下划线的名称:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

或者在特定的模型类上使用这个注释:

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class;)

Jackson 2.7之前,该常量的名称为:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

5
请注意,这仅在Jackson 1.9中引入。 - David Moles
63
@deprecated 自 2.7 版本起使用 SNAKE_CASE 替代; - Thermech
11
自 Jackson 2.12 版本开始,它支持 PropertyNamingStrategies.SNAKE_CASE - Trynkiewicz Mariusz
7
使用Jackson 2.12+的注解时,可以添加@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)来指定序列化和反序列化时采用蛇形命名法。 - Drew Stephens
2
我认为Jackson这个库不是很稳定,常常来回更改它们的常量。 - Praytic
显示剩余7条评论

141

如果是Spring Boot应用程序,在application.properties文件中,只需使用

spring.jackson.property-naming-strategy=SNAKE_CASE

或在模型类上注释此注释。

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)


3
如果我在类上使用 "@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)",它可以工作。但是如果我在 "application.properties" 文件中使用 "spring.jackson.property-naming-strategy=SNAKE_CASE",它就不起作用了。我正在使用 "Spring Boot (v2.0.0.BUILD-SNAPSHOT)"。你有什么想法吗? - Bruno
2
同样的问题,spring.jackson.property-naming-strategy=SNAKE_CASE 不起作用,我正在使用 Spring Boot 2.0。 - soulmachine
1
同样的问题,spring.jackson.property-naming-strategy=SNAKE_CASE不起作用,我正在使用Spring Boot 2.0.5。但是使用注释对我有用。 - Neo Pham
也许你的 ObjectMapper 不是由 Spring 创建的?创建一个 @Configuration 类,并添加一个 @Bean 方法,返回一个 ObjectMapper。不确定是否必要。 - Ondra Žižka
我正在使用Spring Boot 2.4.1,spring.jackson.property-naming-strategy=SNAKE_CASE 对我有效。 - Darotudeen

132

你应该在想要更改默认名称映射的字段上使用@JsonProperty

class User{
    @JsonProperty("first_name")
    protected String firstName;
    protected String getFirstName(){return firstName;}
}

更多信息请参见:API


109
不要这样做,否则你将不得不为每个属性都这样做。请参阅下面thehpi的回复。 - Ryan Shillington
1
我只能注释一个属性,但它确实改变了生成字符串中属性的顺序:带注释的属性最后出现。(Jackson 2.3.0) - eebbesen
1
@RyanShillington - 如果你解析的JSON字符串没有使用一致的格式,即同时使用驼峰式和下划线式,那么这是你唯一的选择,如果我说错了,请纠正我。 - DavidR
@DavidR,没错。我猜你不能修复源数据?那太糟糕了。 - Ryan Shillington
@PaulTsai 好的,随意使用它们 :) - Alex
使用 propertyNamingStrategy 比为每个属性添加注释的方式更好。 - TonyLxc

58
如果您想针对单个类进行此项操作,可以使用PropertyNamingStrategies@JsonNaming注释来实现,如下所示:
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public static class Request {

    String businessName;
    String businessLegalName;

}

将序列化为:

{
    "business_name" : "",
    "business_legal_name" : ""
}

Jackson 2.7之前,请使用PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class

@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public static class Request {

    String businessName;
    String businessLegalName;

}

Jackson 2.7 版本到 Jackson 2.12 版本,LowerCaseWithUnderscoresStrategy 已经被废弃,请使用SnakeCaseStrategy

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public static class Request {

    String businessName;
    String businessLegalName;

}

自从Jackson 2.12版本起,PropertyNamingStrategy.SnakeCaseStrategy已被弃用,应使用 PropertyNamingStrategies.SnakeCaseStrategy。你应该使用以下内容:
    @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
    public static class Request {

        String businessName;
        String businessLegalName;

    }

1
Jackson 2.12 版本开始,请使用 PropertyNamingStrategies.LowerCaseStrategy 替代 PropertyNamingStrategy(注意从 PropertyNamingStrategyPropertyNamingStrategies 的更改):https://fasterxml.github.io/jackson-databind/javadoc/2.13/com/fasterxml/jackson/databind/PropertyNamingStrategies.LowerCaseStrategy.html - SiliconMind

31

关于@JsonPropertyCAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES的回答是100%准确的,尽管有些人(比如我)可能正在尝试在基于代码的Spring MVC应用程序中执行此操作。这里是一个示例代码(我在Beans.java中拥有它),以实现所需的效果:

@Bean
public ObjectMapper jacksonObjectMapper() {
    return new ObjectMapper().setPropertyNamingStrategy(
            PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}

9
如果您使用的是Spring Boot <=1.3,可以使用spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES替代Spring Boot。如果您使用的是Spring Boot 1.4,则应改用spring.jackson.property-naming-strategy=SNAKE_CASE。请注意,这些设置将更改属性名称的命名策略。 - Dump Cake
1
@zapl 是的,你说得对,我可能提到了 Jackson 的版本,而不是 Spring Boot 的版本。让我删除那条评论以避免混淆。 - Ram Patra
1
从Jackson的2.7版本开始,它采用SNAKE_CASE。以下代码对我有效:final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE); - Jonathan

19

当前的最佳实践是在 application.yml(或 properties)文件中配置Jackson。

示例:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE
如果您有更复杂的配置需求,您也可以以编程方式配置Jackson。
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfiguration {

    @Bean
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        return new Jackson2ObjectMapperBuilder()
                .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        // insert other configurations
    }

} 

你知道是否有另一个jackson2objectmapper实例正在加载并覆盖这个实例吗?你能确认即使是这个bean也被加载了吗? - Kenny Cason
也可以试试DuffJ的解决方案。它非常相似。 - Kenny Cason
我认为微调属性是正确的方法,而且也是推荐的。这会做到跟这个一样的效果。 - WesternGun
@WesternGun 好主意。如果可能的话,我倾向于使用yaml/properties来完成这个任务。 - Kenny Cason

13

为了给模型类添加注释,请使用:

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)

改为:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

它自2.12版本以来已被弃用。


6
这里有几个答案,介绍了Jackson库的两个不同版本的策略:
对于Jackson 2.6.*:
ObjectMapper objMapper = new ObjectMapper(new JsonFactory()); // or YAMLFactory()
objMapper.setNamingStrategy(
     PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);

适用于Jackson 2.7.*版本

ObjectMapper objMapper = new ObjectMapper(new JsonFactory()); // or YAMLFactory()
objMapper.setNamingStrategy(
     PropertyNamingStrategy.SNAKE_CASE);

他们再次弃用了一些值,现在有了Kebab Case,太棒了! - Kalpesh Soni
FTR:kebab-case 不是 snake_case ;-) - René

4
注释所有模型类对我来说似乎过度了,而Kenny的答案对我没有用https://dev59.com/DWkv5IYBdhLWcg3wjxdl#43271115。 序列化的结果仍然是驼峰式命名。
我意识到我的Spring配置存在问题,所以我必须从另一个方面解决这个问题。希望有人会发现它有用,但如果我做了违反Spring规则的事,请告诉我。
Spring MVC 5.2.5和Jackson 2.11.2的解决方案。
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);           

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper);
        converters.add(converter);
    }
}

1
  1. 您可以在类的字段上使用@JsonProperty注释,将字段映射到我们JSON中的确切名称

    @JsonProperty("my_name")
    private String myName;
    
  2. 您可以在类上使用@JsonNaming注释,并且所有字段都将使用蛇形命名法进行反序列化

    @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) 
    public class MyClassWithSnakeStrategy { ... 
    

}

  1. 您可以使用setPropertyNamingStrategy方法在ObjectMapper上进行配置,以便进行所有序列化

    ObjectMapper objectMapper = new ObjectMapper()
    .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接