【问题标题】:how to globally define the naming convention with Jackson如何使用 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。

那么如何全局定义序列化的命名约定?

如果不可能,则必须使用本地解决方案。

【问题讨论】:

    标签: java spring spring-boot jackson


    【解决方案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,但我不知道如何解决这个问题。
    • 您可以通过更改 application.properties 来全局执行此操作。只需添加“spring.jackson.property-naming-strategy=UPPER_CAMEL_CASE”即可将所有内容设置为大写
    【解决方案2】:

    其实有一个很简单的答案:

    @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 扩展类)。
    猜你喜欢
    • 2014-08-06
    • 2013-12-13
    • 2017-07-23
    • 2013-08-11
    • 2013-07-19
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多