杰克逊克服下划线支持骆驼案


160

我从互联网上检索了JSON字符串;像大多数JSON一样,我见过它包含用下划线分隔的长键。本质上,我的目标是将JSON反序列化为Java对象,但我不在Java代码中使用下划线。

例如,我可能有一个驼峰式User带有firstName字段的类,同时我还需要某种方式告诉杰克逊将first_name密钥从JSON 映射到firstName类字段。可能吗?

class User{
    protected String firstName;
    protected String getFirstName(){return firstName;}
}

Answers:


103

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

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

有关更多信息:API


86
不要这样做,否则您必须为每个属性都这样做。请参阅下面的thehpi响应。
瑞恩·希灵顿

我只能注释一个属性,但是它确实改变了所生成字符串中属性的顺序:带注释的属性最后出现。(杰克逊2.3.0)
eebbesen 2013年

1
@RyanShillington-如果我错了,请纠正我,但这是您唯一的选择,如果您要解析的JSON字符串不使用一致的格式,即同时使用camelCase和下划线?
DavidR

@DavidR那是正确的。我假设您无法修复源数据?糟透了。
瑞安·希灵顿

@PaulTsai好的,请随时使用它们:)
Alex

351

您可以配置ObjectMapper将驼峰大小写转换为带下划线的名称:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

或使用此注释来注释特定的模型类:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

在Jackson 2.7之前,常量被命名为:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

5
请注意,这仅在Jackson 1.9中引入。
David Moles

62
@deprecated从2.7开始使用SNAKE_CASE代替;
Thermech '16

1
一个qq:当我使用snake_case命名策略时,带有下划线的json文件会反序列化为驼峰式大小写吗?
拉姆·帕特拉

2
@Ramswaroop是的,这使杰克逊既说话又期待snake_case
Drew Stephens

1
@Ramswaroop对我来说,使用Jackson 2.7.3和带有正则注释的属性@JsonProperty(从正常camelCaseJava属性推断出的名称),PropertyNamingStrategy.SNAKE_CASE使得反序列化停止使用camelCase JSON(就像我一直在使用的那样),并且需要snake_case。
德鲁·史蒂芬斯

119

如果它是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)”。你有什么想法 ?
布鲁诺

1
同样在这里,spring.jackson.property-naming-strategy=SNAKE_CASE不起作用,我正在使用Spring Boot 2.0
soulmachine'Apr

1
同样在这里,spring.jackson.property-naming-strategy = SNAKE_CASE不起作用,我使用的是Spring Boot 2.0.5。但是使用注释对我来说是有效的
Neo Pham

也许您ObjectMapper不是由Spring创建的?使用返回一个ObjectMapper的@Bean方法创建一个@Configuration类。不知道这是否必要。
OndraŽižka,

48

如果您希望将其用于单个类,则可以将PropertyNamingStrategy@JsonNaming结合使用,如下所示:

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

    String businessName;
    String businessLegalName;

}

将序列化为:

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

由于Jackson 2.7LowerCaseWithUnderscoresStrategy中弃用,取而代之的SnakeCaseStrategy,所以你应该使用:

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

    String businessName;
    String businessLegalName;

}

29

上面的答案关于@JsonProperty和,CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES它们都是100%准确的,尽管有些人(例如我)可能正在尝试使用基于代码的配置在Spring MVC应用程序中执行此操作。这是Beans.java实现所需效果的示例代码(我在inside ):

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

9
如果您使用的是Spring Boot <= 1.3,请在application.propertiesadd中使用Spring Boot的替代方法spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES。对于Spring Boot 1.4,请spring.jackson.property-naming-strategy=SNAKE_CASE改用。
转储蛋糕

1
@zapl是的,您是对的,我可能提到了杰克逊的版本,而不是spring-boot的版本。让我删除该评论以避免混淆。
拉姆·帕特拉

1
从Jackson的2.7版本开始,它是SNAKE_CASE。这对我final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
Jonathan

12

当前的最佳实践是在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?
肯尼·卡森

同时给DuffJ的解决方案一个漩涡。非常相似。
肯尼·卡森

我认为调整属性是正确的方法;并推荐了。与此相同。
WesternGun

@WesternGun好电话。我倾向于在可能的情况下通过yaml / properties做到这一点。
肯尼·卡森

6

此处几乎没有答案指出下面两种不同版本的Jackson库的两种策略:

对于杰克逊2.6。*

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

对于杰克逊2.7。*

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

他们再次弃用了一些值,现在有了KEBAB_CASE,好极了!
Kalpesh Soni,

FTR:烤肉情况不snake_case ;-)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.