Course – LS (cat=JSON/Jackson)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this quick tutorial, we will analyze the marshalling of entities with no getters and the solution for the Jackson JsonMappingException exception.

If you want to dig deeper and learn other cool things you can do with the Jackson 2 – head on over to the main Jackson tutorial.

Further reading:

Intro to the Jackson ObjectMapper

The article discusses Jackson's central ObjectMapper class, basic serialization and deserialization as well as configuring the two processes.

Using Optional with Jackson

A quick overview of how we can use the Optional with Jackson.

Spring JSON-P with Jackson

The article is focused on showing how to use the new JSON-P support in Spring 4.1.

2. The Problem

By default, Jackson 2 will only work with fields that are either public, or have a public getter methods – serializing an entity that has all fields private or package private will fail:

public class MyDtoNoAccessors {
    String stringValue;
    int intValue;
    boolean booleanValue;

    public MyDtoNoAccessors() {
        super();
    }

    // no getters
}
@Test(expected = JsonMappingException.class)
public void givenObjectHasNoAccessors_whenSerializing_thenException() 
  throws JsonParseException, IOException {
    String dtoAsString = new ObjectMapper().writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, notNullValue());
}

The full exception is:

com.fasterxml.jackson.databind.JsonMappingException: 
No serializer found for class dtos.MyDtoNoAccessors 
and no properties discovered to create BeanSerializer 
(to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )

3. The Solution

The obvious solution is to add getters for the fields – if the entity is under our control. If that is not the case and modifying the source of the entity is not possible – then Jackson provides us with a few alternatives.

3.1. Globally Auto Detect Fields With Any Visibility

A first solution to this problem is to globally configure the ObjectMapper to detect all fields, regardless of their visibility:

objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

This will allow the private and package private fields to be detected without getters, and serialization will work correctly:

@Test
public void givenObjectHasNoAccessors_whenSerializingWithAllFieldsDetected_thenNoException() 
  throws JsonParseException, IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
    String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, containsString("intValue"));
    assertThat(dtoAsString, containsString("stringValue"));
    assertThat(dtoAsString, containsString("booleanValue"));
}

3.2. Detected All Fields at the Class Level

Another option Jackson 2 provides is – instead of the global configuration – control the field visibility at the class level via the @JsonAutoDetect annotation:

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class MyDtoNoAccessors { ... }

With this annotation, the serialization should now work correctly with this particular class:

@Test
public void givenObjectHasNoAccessorsButHasVisibleFields_whenSerializing_thenNoException() 
  throws JsonParseException, IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, containsString("intValue"));
    assertThat(dtoAsString, containsString("stringValue"));
    assertThat(dtoAsString, containsString("booleanValue"));
}

4. Disable fail_on_empty_beans in Jackson

In Jackson, the fail_on_empty_beans feature determines whether an exception should be thrown if an object being serialized is empty (has no properties). By default, Jackson throws an exception if it encounters an empty bean during serialization.

It’s worth noting that the fail_on_empty_beans feature is enabled by default, so if we want to disable it, we need to explicitly set it to false. To do so, we can use two approaches depending on our specific use case.

4.1. Using Object Mapper Configuration

We can disable fail_on_empty_beans using the ObjectMapper directly:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

By configuring the ObjectMapper in this way, we are telling Jackson not to throw an exception when encountering an empty bean during the serialization process.

4.2. Using Spring Boot

In Spring Boot, we can set the following property in the application.properties file to disable fail_on_empty_beans globally:

spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false

This property can be set at the application level to control the behavior of Jackson serialization across the entire application.

5. Conclusion

This article illustrated how to get around the default field visibility in Jackson, by configuring a custom visibility either globally on the ObjectMapper or on individual classes. Jackson allows even further customization by providing options to control exactly how getters, setters or fields with specific visibilities are seen by the mapper.

The implementation of all these examples and code snippets can be found in my GitHub project – this is an Eclipse-based project, so it should be easy to import and run as it is.

Course – LS (cat=JSON/Jackson)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – Jackson (eBook) (cat=Jackson)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.