JSON Property Name Customization in Jackson using PropertyNamingStrategy

Jackson is one of the most popular java libraries for serialization/deserialization of POJOs to/from JSON. By default, Jackson derives the JSON element names from the getter/setter method names of the POJO. e.g. getActorName() is translated to actorName in the resulting JSON.

Let's take the following POJO and serialization function for our examples.

//The POJO that needs to be serialized
public class Actor {
 private String actorName;
 private Gender actorGender;
 public Actor() {}
 public Actor(String name, Gender gender) {
  this.actorName = name; this.actorGender = gender;
 }
 public String getActorName() {
  return actorName;
 }
 public void setActorName(String actorName) {
  this.actorName = actorName;
 }
 public Gender getActorGender() {
  return actorGender;
 }
 public void setActorGender(Gender actorGender) {
  this.actorGender = actorGender;
 }
}

//Code that serializes the actor object to JSON
Actor actor = new Actor("Al Pacino", Gender.MALE);
ObjectMapper mapper = new ObjectMapper();
Writer w = new StringWriter();
mapper.writeValue(w, actor);
System.out.println(w.toString());

//The resulting JSON with default camelcase
{
 "actorName":"Al Pacino",
 "actorGender":"MALE"
}

Customizing element names


Jackson allows you to change this default behavior through PropertyNamingStrategy.
PropertyNamingStrategy provides a few template methods that can be overridden to derive custom element names from the method names (for serialization) and vice-versa (for deserialization).

nameForGetterMethod resolves the element names for the given getter method during serialization.
nameForSetterMethod identifies the element names for the given setter method during deserialization.

This strategy can then be set on the ObjectMapper, before reading or writing to it.

mapper.setPropertyNamingStrategy(myStrategyInstance);

Jackson Strategies


Jackson provides at least two Strategies out of the box.

LowerCaseWithUnderscoresStrategy - It converts camel case properties to lowercase element names separated by underscores. It's a private class and can't be used directly. Instead, it can be used in the following manner.
mapper.setPropertyNamingStrategy(
      PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);

//The resulting JSON with underscores
{
 "actor_name":"Al Pacino",
 "actor_gender":"MALE"
}

PascalCaseStrategy - It converts camel case properties to PascalCase element names.
mapper.setPropertyNamingStrategy(
      PropertyNamingStrategy.PASCAL_CASE_TO_CAMEL_CASE);

//The resulting JSON with PascalCase elements
{
 "ActorName":"Al Pacino",
 "ActorGender":"MALE"
}


Custom strategies


You can also define a custom strategy of your own. The AllLowerCasePropertyNamingStrategy defined below converts the property names to lowercase element names. The defaultName here is the element name that the default strategy provides.

public class AllLowerCasePropertyNamingStrategy extends PropertyNamingStrategy {
     
    @Override
    public String nameForGetterMethod(MapperConfig config,
            AnnotatedMethod method, String defaultName) {
        return defaultName.toLowerCase();
    }

    @Override
    public String nameForSetterMethod(MapperConfig config,
            AnnotatedMethod method, String defaultName) {
        return defaultName.toLowerCase();
    }
    
}

mapper.setPropertyNamingStrategy(
      new AllLowerCasePropertyNamingStrategy());

//The resulting JSON with lowercase element names
{
 "actorname":"Al Pacino",
 "actorgender":"MALE"
}

Another example of a custom strategy, StripPrefixPropertyNamingStrategy, strips the given prefix from the property names to derive the element names.

private static class StripPrefixPropertyNamingStrategy extends PropertyNamingStrategy {

 private String prefix;

 public StripPrefixPropertyNamingStrategy(String prefix) {
  this.prefix = prefix;
 }

 @Override
 public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) {
  return defaultName.replaceFirst(prefix, "");
 }

 @Override
 public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) {
  return defaultName.replaceFirst(prefix, "");
 }

}

mapper.setPropertyNamingStrategy(
      new StripPrefixPropertyNamingStrategy("actor"));

//The resulting JSON without the actor prefix
{
 "Name":"Al Pacino",
 "Gender":"MALE"
}


No comments:

Post a Comment