【问题标题】:Jackson overcoming underscores in favor of camel-case杰克逊克服下划线支持骆驼案
【发布时间】:2012-05-18 03:44:19
【问题描述】:

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

例如,我可能有一个 User 类和骆驼案例中的 firstName 字段,同时我需要以某种方式告诉 Jackson 将 first_name 键从 JSON 映射到 firstName 类字段。有可能吗?

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

【问题讨论】:

    标签: java jackson


    【解决方案1】:

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

    objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
    

    或者用这个注解来注解一个特定的模型类:

    @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
    

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

    PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
    

    【讨论】:

    • 请注意,这只在 Jackson 1.9 中引入。
    • @deprecated 从 2.7 开始使用 SNAKE_CASE;
    • @Ramswaroop 是的,这让杰克逊既说话又期待蛇案例
    • 从 Jackson 2.12 开始是 PropertyNamingStrategies.SNAKE_CASE
    • 在 Jackson 2.12+ 中使用注释时:@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
    【解决方案2】:

    如果是spring boot应用,在application.properties文件中使用

    spring.jackson.property-naming-strategy=SNAKE_CASE

    或者用这个注解来注解模型类。

    @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

    【讨论】:

    • 如果我用“@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)”注释我的班级,它就可以工作。但是如果我在“application.properties”中使用“spring.jackson.property-naming-strategy=SNAKE_CASE”,它不会。我正在使用“Spring Boot (v2.0.0.BUILD-SNAPSHOT)”。你有什么想法吗?
    • 这里一样,spring.jackson.property-naming-strategy=SNAKE_CASE 不起作用,我使用的是 Spring Boot 2.0
    • 这里一样,spring.jackson.property-naming-strategy=SNAKE_CASE 不起作用,我使用的是 Spring Boot 2.0.5。但是使用注释对我有用
    • 也许你的ObjectMapper不是由Spring创建的?使用返回 ObjectMapper 的 @Bean 方法创建 @Configuration 类。不确定这是否有必要。
    • 我正在使用 Spring boot 2.4.1 和 spring.jackson.property-naming-strategy=SNAKE_CASE 为我工作
    【解决方案3】:

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

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

    欲了解更多信息:API

    【讨论】:

    • 不要这样做,否则您将不得不为每个属性都这样做。请参阅下面 thehpi 的回复。
    • 我只能注释一个属性,但它确实改变了生成字符串中属性的顺序:注释的属性最后出现。 (杰克逊 2.3.0)
    • @RyanShillington - 如果我错了,请纠正我,但如果您解析的 JSON 字符串不使用一致的格式,即同时使用驼峰式和下划线,这是您唯一的选择?跨度>
    • @DavidR 没错。我假设您无法修复源数据?太糟糕了。
    • @PaulTsai 好的,所以请随意使用它们 :)
    【解决方案4】:

    如果您想在单个类中使用此功能,可以使用 PropertyNamingStrategy@JsonNaming,如下所示:

    @JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
    public static class Request {
    
        String businessName;
        String businessLegalName;
    
    }
    

    将序列化为:

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

    由于Jackson 2.7 LowerCaseWithUnderscoresStrategySnakeCaseStrategy 弃用,所以你应该使用:

    @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
    public static class Request {
    
        String businessName;
        String businessLegalName;
    
    }
    

    【讨论】:

      【解决方案5】:

      上述关于@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);
      }
      

      【讨论】:

      • Spring Boot 的替代方案,如果您使用的是 Spring Boot application.properties 添加 spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES。对于 Spring Boot 1.4,请改用 spring.jackson.property-naming-strategy=SNAKE_CASE
      • @zapl 是的,你是对的,我可能提到了杰克逊的版本而不是 spring-boot 的版本。让我删除该评论以避免混淆。
      • 从 Jackson 的 2.7 版开始,它是 SNAKE_CASE。这对我有用:final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
      【解决方案6】:

      当前的最佳做法是在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 好电话。如果可能,我倾向于通过 yaml/properties 执行此操作。
      【解决方案7】:

      这里很少有答案表明以下两种不同版本的 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 ,嗯!
      • FTR: kebab-case 不是snake_case ;-)
      【解决方案8】:

      注释所有模型类在我看来是一种矫枉过正,而 Kenny 的回答对我不起作用https://stackoverflow.com/a/43271115/4437153。序列化的结果还是驼峰式的。

      我意识到我的弹簧配置有问题,所以我不得不从另一个方面解决这个问题。希望有人觉得它有用,但如果我在做违反 springs 规则的事情,请告诉我。

      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);
          }
      }
      

      【讨论】:

        【解决方案9】:

        为了注释模型类使用:

        @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
        

        代替:

        @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
        

        自 2.12 起已弃用。

        【讨论】:

          【解决方案10】:
          1. 您可以在我们类的字段上使用@JsonProperty 注解将字段映射到我们JSON 中的确切名称

            @JsonProperty("my_name")
            private String myName;
            
          2. 可以在类上使用@JsonNaming注解,所有字段都会使用snake case反序列化

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

          }

          1. 您可以使用 ObjectMapper 上的 setPropertyNamingStrategy 方法来配置它以进行所有序列化

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

          【讨论】:

            猜你喜欢
            • 2016-09-10
            • 1970-01-01
            • 2017-08-22
            • 2015-05-27
            • 1970-01-01
            • 2013-10-16
            • 2018-10-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多