Jackson - JsonMappingException (Kein Serializer für Klasse gefunden)

Jackson - JsonMappingException (Kein Serializer für Klasse gefunden)

1. Überblick

In diesem kurzen Tutorial analysieren wir das Marshalling von Entitäten ohne Getter undthe solution for the Jackson JsonMappingException exception.

Wenn Sie tiefer graben undother cool things you can do with the Jackson 2 lernen möchten, gehen Sie zuthe main Jackson tutorial.

Weitere Lektüre:

Einführung in den Jackson ObjectMapper

Der Artikel beschreibt Jacksons zentrale ObjectMapper-Klasse, die grundlegende Serialisierung und Deserialisierung sowie die Konfiguration der beiden Prozesse.

Read more

Optional mit Jackson verwenden

Ein kurzer Überblick darüber, wie wir die Option mit Jackson verwenden können.

Read more

Spring JSON-P mit Jackson

Der Artikel befasst sich mit der Verwendung der neuen JSON-P-Unterstützung in Spring 4.1.

Read more

2. Das Problem

Standardmäßig funktioniert Jackson 2 nur mit Feldern, die entweder öffentlich sind oder über öffentliche Getter-Methoden verfügen -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());
}

Dasfull exception ist:

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. Die Lösung

Die naheliegende Lösung besteht darin, Getter für die Felder hinzuzufügen - wenn die Entität unter unserer Kontrolle steht. Wenn dies nicht der Fall ist undmodifying the source of the entity is not possible - dann bietet Jackson uns einige Alternativen.

3.1. Globale automatische Erkennung von Feldern mit beliebiger Sichtbarkeit

Eine erste Lösung für dieses Problem besteht darin, dieObjectMapper so zu konfigurieren, dass alle Felder unabhängig von ihrer Sichtbarkeit erkannt werden:

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

Dies wirdallow the private and package private fields to be detected ohne Getter sein und die Serialisierung wird korrekt funktionieren:

@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. Alle Felder auf Klassenebene erkannt

Eine weitere Option, die Jackson 2 bietet, ist - anstelle der globalen Konfiguration -control the field visibility at the class level über die Annotation@JsonAutoDetect:

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

Mit dieser Annotation sollte die Serialisierung nun mit dieser bestimmten Klasse korrekt funktionieren:

@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. Fazit

In diesem Artikel wurde veranschaulicht, wieget around the default field visibility in Jackson ausgeführt werden, indem eine benutzerdefinierte Sichtbarkeit entweder global fürObjectMapper oder für einzelne Klassen konfiguriert wird. Jackson ermöglicht noch weitere Anpassungen, indem Optionen bereitgestellt werden, mit denen genau gesteuert werden kann, wie Getter, Setter oder Felder mit bestimmten Sichtbarkeiten vom Mapper gesehen werden.

Die Implementierung all dieser Beispiele und Codefragmentecan be found in my github project - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.