Course – launch – BF – 2023 Discount 30%
We're now running the only sale of the year - our Black Friday launch. All Courses are 30% off until end-of-day today:

>> EXPLORE ACCESS NOW

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 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. 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 – launch – BF – 2023 Discount 30%
We're now running the only sale of the year - our Black Friday launch. All Courses are 30% off until end-of-day today:

>> EXPLORE ACCESS NOW

res – Jackson (eBook) (cat=Jackson)
Comments are closed on this article!