user1384991
user1384991

Reputation: 2629

Jackson overcoming underscores in favor of camel-case

I retrieve a JSON string from internet; like most JSON I've seen it includes long keys that are separated by underscores. Essentially, my goal is to deserialize JSON into java-objects, but I don't use underscores in java-code.

For instance, I might have a User class with firstName field in camel-case, simultaneously I need somehow to tell Jackson to map first_name key from JSON to firstName class field. Is it possible?

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

Upvotes: 220

Views: 212796

Answers (11)

thehpi
thehpi

Reputation: 5833

In Jackson 2.12+, you can configure the ObjectMapper to convert camel case to names with an underscore:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

Or annotate a specific model class with this annotation:

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)

Before Jackson 2.7, the constant was named:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES

Upvotes: 486

Arturo Volpe
Arturo Volpe

Reputation: 3627

If you want this for a Single Class, you can use the PropertyNamingStrategies with the @JsonNaming, annotation, like this:

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

    String businessName;
    String businessLegalName;

}

Will serialize to:

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

Before Jackson 2.7, use PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class:

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

    String businessName;
    String businessLegalName;

}

From Jackson 2.7 to Jackson 2.12 the LowerCaseWithUnderscoresStrategy is deprecated in favor of SnakeCaseStrategy, so you should use:

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

    String businessName;
    String businessLegalName;

}

Since Jackson 2.12 the PropertyNamingStrategy.SnakeCaseStrategy is deprecated in favor of PropertyNamingStrategies.SnakeCaseStrategy, you should use:

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

        String businessName;
        String businessLegalName;

    }

Upvotes: 60

Fuzhe Jerry LI
Fuzhe Jerry LI

Reputation: 29

PropertyNamingStrategy should be replaced with PropertyNamingStrategies for @JsonNaming

Upvotes: 0

Forgery
Forgery

Reputation: 98

  1. You can use the @JsonProperty annotation on the fields of our class to map the fields to the exact names in our JSON

    @JsonProperty("my_name")
    private String myName;
    
  2. You can use @JsonNaming annotation on the class, and all fields will be deserialized using snake case

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

}

  1. You can use the setPropertyNamingStrategy method on ObjectMapper to configure it for all serialization

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

Upvotes: 1

andreyt
andreyt

Reputation: 131

In order to annotate the model class use:

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)

Instead of:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

It was deprecated since 2.12.

Upvotes: 13

rudald
rudald

Reputation: 404

Annotating all model classes looks to me as an overkill and Kenny's answer didn't work for me https://stackoverflow.com/a/43271115/4437153. The result of serialization was still camel case.

I realised that there is a problem with my spring configuration, so I had to tackle that problem from another side. Hopefully someone finds it useful, but if I'm doing something against springs' rules then please let me know.

Solution for Spring MVC 5.2.5 and 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);
    }
}

Upvotes: 4

Kenny Cason
Kenny Cason

Reputation: 12328

The current best practice is to configure Jackson within the application.yml (or properties) file.

Example:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

If you have more complex configuration requirements, you can also configure Jackson programmatically.

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
    }

} 

Upvotes: 19

Amit Kaneria
Amit Kaneria

Reputation: 5808

There are few answers here indicating both strategies for 2 different versions of Jackson library below:

For Jackson 2.6.*

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

For Jackson 2.7.*

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

Upvotes: 6

adam.smithsonian01
adam.smithsonian01

Reputation: 1420

If its a spring boot application, In application.properties file, just use

spring.jackson.property-naming-strategy=SNAKE_CASE

Or Annotate the model class with this annotation.

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

Upvotes: 142

Dawngerpony
Dawngerpony

Reputation: 3573

The above answers regarding @JsonProperty and CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES are 100% accurate, although some people (like me) might be trying to do this inside a Spring MVC application with code-based configuration. Here's sample code (that I have inside Beans.java) to achieve the desired effect:

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

Upvotes: 31

Alex
Alex

Reputation: 25613

You should use the @JsonProperty on the field you want to change the default name mapping.

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

For more info: the API

Upvotes: 132

Related Questions