Jackson – JsonMappingException (No serializer found for class)

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.

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.

I usually post about Dev stuff on Google+ - you can follow me there:

Get My 3 Spring eBooks
Learn how to properly build Web App with Spring (and how to prototype 90% of it very quickly)
×
Download the 3 eBooks - Build Your App "The Right Way"