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

1. Übersicht

In diesem kurzen Tutorial analysieren wir das Marshalling von Entitäten ohne Getter und die Lösung für die Jackson JsonMappingException- Ausnahme .

Wenn Sie tiefer graben und andere coole Dinge lernen möchten, die Sie mit dem Jackson 2 tun können, besuchen Sie das Haupt-Tutorial von Jackson.

2. Das Problem

Standardmäßig funktioniert Jackson 2 nur mit Feldern, die entweder öffentlich sind oder über öffentliche Getter-Methoden verfügen. Die Serialisierung einer Entität mit allen privaten Feldern oder privaten Paketen schlägt fehl :

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()); }

Die vollständige Ausnahme 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 - sofern die Entität unter unserer Kontrolle steht. Wenn dies nicht der Fall ist und eine Änderung der Entitätsquelle nicht möglich ist, bietet Jackson uns einige Alternativen.

3.1. Felder mit jeder Sichtbarkeit global automatisch erkennen

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

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

Auf diese Weise können die privaten und privaten Paketfelder ohne Getter erkannt werden, und die Serialisierung funktioniert ordnungsgemäß:

@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, besteht darin, anstelle der globalen Konfiguration die Feldsichtbarkeit auf Klassenebene über die Annotation @JsonAutoDetect zu steuern :

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

Mit dieser Anmerkung sollte die Serialisierung jetzt 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 erläutert, wie Sie die Standard-Feldsichtbarkeit in Jackson umgehen können , indem Sie eine benutzerdefinierte Sichtbarkeit entweder global im ObjectMapper oder in einzelnen Klassen konfigurieren . Jackson ermöglicht eine weitere Anpassung, 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 Codefragmente finden Sie in meinem GitHub-Projekt - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.