ジャクソン– JsonMappingException(クラスのシリアライザーが見つかりません)
1. 概要
このクイックチュートリアルでは、ゲッターとthe solution for the Jackson JsonMappingException exceptionを使用しないエンティティのマーシャリングを分析します。
さらに深く掘り下げてother cool things you can do with the Jackson 2を学びたい場合は、the main Jackson tutorialに進んでください。
参考文献:
Jackson ObjectMapperの紹介
この記事では、Jacksonの中心的なObjectMapperクラス、基本的なシリアル化と逆シリアル化、および2つのプロセスの構成について説明します。
2. 問題
デフォルトでは、Jackson 2は、パブリックであるか、パブリックゲッターメソッドを持つフィールドでのみ機能します–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());
}
full exceptionは次のとおりです。
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. ソリューション
明らかな解決策は、エンティティが制御下にある場合、フィールドにゲッターを追加することです。 そうではなく、modifying the source of the entity is not possibleの場合、Jacksonはいくつかの選択肢を提供します。
3.1. 可視性のあるフィールドをグローバルに自動検出
この問題の最初の解決策は、可視性に関係なく、すべてのフィールドを検出するようにObjectMapperをグローバルに構成することです。
objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
これはゲッターなしでallow the private and package private fields to be detectedになり、シリアル化は正しく機能します。
@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. クラスレベルですべてのフィールドを検出
Jackson 2が提供するもう1つのオプションは、グローバル構成の代わりに、@JsonAutoDetectアノテーションを介したcontrol the field visibility at the class levelです。
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class MyDtoNoAccessors { ... }
このアノテーションを使用すると、この特定のクラスでシリアル化が正しく機能するようになります。
@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. 結論
この記事では、ObjectMapperまたは個々のクラスのいずれかでカスタム可視性をグローバルに構成することにより、get around the default field visibility in Jacksonを実行する方法を説明しました。 ジャクソンは、特定の可視性を持つゲッター、セッター、またはフィールドがマッパーに表示される方法を正確に制御するオプションを提供することにより、さらにカスタマイズすることができます。
これらすべての例とコードスニペットcan be found in my github projectの実装–これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。