10

I'm using Jackson with Spring. I have a few methods like this:

@RequestMapping(value = "/myURL", method = RequestMethod.GET)
public @ResponseBody Foo getFoo()  {
    // get foo
    return foo;
}

The class Foo that's serialized is quite big and has many members. The serialization is ok, using annotation or custom serializer.

The only thing I can't figure out is how to define the naming convention. I would like to use snake_case for all the serializations.

So how do I define globally the naming convention for the serialization?

If it's not possible, then a local solution will have to do then.

dimitrisli
  • 20,895
  • 12
  • 59
  • 63
dyesdyes
  • 1,147
  • 3
  • 24
  • 39

3 Answers3

13

Not sure how to do this globally but here's a way to do it at the JSON object level and not per each individual property:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class Foo {
    private String myBeanName;
    //...
}

would yield json:

{
    "my_bean_name": "Sth"
    //...
}
dimitrisli
  • 20,895
  • 12
  • 59
  • 63
  • I tried this approach but I receive an error: -- HttpMessageNotWritableException: Could not write content: Type com.fasterxml.jackson.databind.PropertyNamingStrategy$SnakeCaseStrategy not present (through reference chain: java.util.ArrayList[0]); -- This is probably because I return List, but I don't know how to fix this. – dyesdyes Aug 17 '16 at 07:07
  • You can do it globally by changing application.properties. Just add "spring.jackson.property-naming-strategy=UPPER_CAMEL_CASE" to set everything to upper case – WitnessTruth Oct 30 '20 at 18:34
5

Actually, there was a really simple answer:

@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
    b.propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
    return b;
}

I added it in my main like so:

@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;
    }
}
Community
  • 1
  • 1
dyesdyes
  • 1,147
  • 3
  • 24
  • 39
  • CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES has been deprecated since 2.7, use SNAKE_CASE instead. – Fuping Oct 05 '17 at 05:53
1

The mapper has a setter for PropertyNamingStrategy (Method for setting custom property naming strategy to use.)

Look how it works in the tes example:

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

Output:

{
  "SOMEIDATTACHEDTOIT" : "uuid_1",
  "USERNAME" : "user_1",
  "FISTNAME" : "Bruce",
  "LASTNAME" : "W.",
  "AGE" : 51
}

Provided strategies (I use LOWERCASE for the examples)

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
PropertyNamingStrategy.SNAKE_CASE

To add your strategy globally in Spring, you can do it at least in 2 ways:

  • with a mapper module declared as a bean containing the naming strategy
  • with a custom object mapper configured as you want

Short version:

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

Long version:

To declare the bean for the jackson module:

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

}

You can declare the bean in xml as well.

It won't override @JsonProperty that define the prop name explicitly.

chikincrow
  • 393
  • 3
  • 11
  • Am I supposed to do something with the Confid class? Hook it somewhere? – dyesdyes Aug 17 '16 at 07:05
  • Yes, just create it in a package that Spring can autoscan at startup. It is just to hold the bean declaration. You can create it with xml config as well (need to create your own SimpleModule extension class). – chikincrow Aug 17 '16 at 18:58