Jackson – Custom Serialization and Deserialization of Booleans

Learn Jackson’s default serialization and deserialization of booleans values, and how to customize it to support other possible values such as “0, 1”, “active, inactive” or “enabled, disabled”.

1. Setup

Include the latest version of Jackson in the project, if not included already.

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.13.3</version>
</dependency>

For demo purposes, we will use the following Employee class.

public class Employee {

  private Long id;
  private String name;
  private boolean active;
  private boolean workFromHome;

  //Constructors, setters, getters and toString
}

For serialization, we will be creating a new Employee as follows:

Employee employee = new Employee(1L, "Alex", true, false);

2. Jackson’s Default Behavior

By default, Jackson has the following behavior:

  • It serializes the boolean or Boolean values to JSON boolean values true and false (without quotes).
  • It deserializes the values 'true/false' and '1/0' to boolean/Boolean types.

The following code serializes the Employee instance to JSON. Notice the boolean values have been serialized to ‘true/false’.

void testDefaultSerialization_ThenSuccess() throws JsonProcessingException {

  JsonMapper jsonMapper = new JsonMapper();
  String json = jsonMapper.writeValueAsString(employee);

  Assertions.assertEquals("{\"id\":1,\"name\":\"Alex\",\"active\":true,\"workFromHome\":false}", json);
}

While deserializing, we can use either true/false or 1/0 as boolean values, and Jackson will take care of the conversion.

String json = "{\"id\":1,\"name\":\"Alex\",\"active\":true,\"workFromHome\":false}";

// Using 1 and 0 also works fine
//String json = "{\"id\":1,\"name\":\"Alex\",\"active\":1,\"workFromHome\":0}";

JsonMapper jsonMapper = new JsonMapper();
Employee employee = jsonMapper.readValue(json, Employee.class);

Assertions.assertEquals(employee.isActive(), true);
Assertions.assertEquals(employee.isWorkFromHome(), false);

See Also: Read and Write JSON with Jackson

3. Configuring Default Serialization to Numbers

3.1. Field Level Configuration using @JsonFormat

By default, Jackson serializes the boolean fields to JSON true and false values. If we want the default serialization to produce numbers 1 and 0 for boolean fields then we can use @JsonFormat annotation at field level.

public class Employee { 
	...
	
  @JsonFormat(shape = JsonFormat.Shape.NUMBER)
  private boolean active;

  @JsonFormat(shape = JsonFormat.Shape.NUMBER)
  private boolean workFromHome;

  ...
}

Now when serializing the Employee instance, we get the values {1, 0} instead of {true, false}.

@Test
void testSerialization_FieldLevelJsonFormat_ThenSuccess() throws JsonProcessingException {
  JsonMapper jsonMapper = new JsonMapper();
  String json = jsonMapper.writeValueAsString(employee);

  Assertions.assertEquals("{\"id\":1,\"name\":\"Alex\",\"active\":1,\"workFromHome\":0}", json);
}

3.2. Global Configuration

We can use jsonMapper.configOverride() to configure this behavior, globally. Be careful of the boolean type to configure because types boolean and Boolean are NOT treated same.

JsonMapper jsonMapper = new JsonMapper();

jsonMapper.configOverride(boolean.class)	//boolean
    .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.NUMBER));

4. Custom Serialization and Deserialization

4.1. Custom Deserializer

In real-world applications, we may get data from various sources, and they may use their own values for representing boolean values in JSON data. The following are a few of the possible combinations:

  • 1 and 0
  • true and false
  • “true” and “false”
  • “active” and “inactive”
  • “enabled” and “disabled”

To support all such combinations, we must create a custom deserializer.

class CustomBooleanDeserializer extends JsonDeserializer<Boolean> {

  @Override
  public Boolean deserialize(JsonParser p, DeserializationContext ctx) throws IOException {

    if (List.of("1", "active", "true", "enabled").contains(p.getText())) {
      return Boolean.TRUE;
    }
    else if (List.of("0", "inactive", "false", "disabled").contains(p.getText())) {
      return Boolean.FALSE;
    }
    return null;
  }
}

To use this custom deserializer, we can create a SimpleModule and register it with JsonMapper.

JsonMapper jsonMapper = new JsonMapper();

SimpleModule module = new SimpleModule();
module.addDeserializer(boolean.class, new CustomBooleanDeserializer());
jsonMapper.registerModule(module);

Let us test the custom deserializer using the values ‘active/inactive’ to represent boolean values in JSON.

@Test
void testCustomDeserialization_ThenSuccess() throws JsonProcessingException {

  String json = "{\"id\":1,\"name\":\"Alex\",\"active\":\"active\",\"workFromHome\":\"inactive\"}";

  JsonMapper jsonMapper = new JsonMapper();

  SimpleModule module = new SimpleModule();
  module.addDeserializer(boolean.class, new CustomBooleanDeserializer());
  module.addSerializer(boolean.class, new CustomBooleanSerializer());
  jsonMapper.registerModule(module);

  Employee employee = jsonMapper.readValue(json, Employee.class);

  Assertions.assertEquals(employee.isActive(), true);
  Assertions.assertEquals(employee.isWorkFromHome(), false);
}

4.2. Custom Serializer

Similarly, if we want to write any non-conventional values for boolean fields then we can write the custom serializer as follows:

class CustomBooleanSerializer extends JsonSerializer<Boolean> {
  @Override
  public void serialize(Boolean value, JsonGenerator gen, SerializerProvider serializers)
      throws IOException {
    gen.writeString(value ? "1" : "0");
  }
}

The registration will be done similar to the custom deserializer in the previous example.

JsonMapper jsonMapper = new JsonMapper();

SimpleModule module = new SimpleModule();
module.addDeserializer(boolean.class, new CustomBooleanDeserializer());
module.addSerializer(boolean.class, new CustomBooleanSerializer());
jsonMapper.registerModule(module);

5. Conclusion

In this Jackson tutorial, we learned to customize the default behavior of Jackson when serializing and deserializing the boolean values in JSON format. We learned to use the field-level configurations, global configurations and custom serializer/deserializers as well.

Happy Learning !!

Sourcecode On Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.