この記事で伝えたいこと
FasterXML/jackson: Main Portal page for the Jackson project の version 2 の ObjectMapper のパッケージは、以下 com.fasterxml.jackson.databind
になります。
import com.fasterxml.jackson.databind.ObjectMapper
これに対して、version 1 の ObjectMapper のパッケージは、org.codehaus.jackson.map
で、version 1 と、version 2 ではパッケージが異なります。
import org.codehaus.jackson.map.ObjectMapper;
version 1 時代に作ったライブラリと、version 2 に依存するライブラリを使っていると、思いもしないエラーが発生するので気をつけましょう。
ちなみに現状(2017/10/08) の最新 version は、Maven Repository: com.fasterxml.jackson.core » jackson-core » 2.9.1 です。
問題となった実装と、発生したエラー
問題となった実装
Jackson
で Json
を JavaObject
に変換したいので、以下のような実装で Convert
しようしていました。
// Do Something...
// -----------------------------------
// ConvertValue
// ------------
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
CollectionLikeType jt = mapper.getTypeFactory().constructCollectionType(List.class, clazz);
return mapper.convertValue(results, jt);
発生したエラー
実際実行すると以下のエラーが発生しました。
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "xxx" (Class xxx.dto.License), not marked as ignorable
一般的に上記のエラーが発生するパターン
Web
検索では、以下のような記事がヒットしました。
* jacksonでデシリアライズする際に未知のプロパティを無視する - するめとめがね
Convert
対象の Java
クラスに、@JsonIgnoreProperties
アノテーションを付与して、知らないフィールドがきても無視する設定をすれば、エラーは解消されます。
無視してよいフィールドであれば、以下のように、@JsonIgnoreProperties
アノテーションを付与することを検討、付与されていることを確認してください。
@JsonIgnoreProperties(ignoreUnknown = true)
今回エラーが発生したケース
@JsonIgnoreProperties
付けていないのが問題ではなかった
そもそも対象の Java
クラスのエラーとなったフィールドには、@JsonProperty
アノテーションの記述を施してあり、Unknown Field
ではないだろこの野郎と思っていました。
@JsonProperty("xxx")
private Integer xxxRank;
@JsonIgnoreProperties
を付与しなくても、処理は実施してくれるはずです。 原因がよくわからず、小一時間
Web
検索していたところ、以下の記事を見つけました。
「 org.codehaus.jackson
は version1
だよ。古いよ。com.fasterxml.jackson
が version2
で新しいやつだよ」
との旨が記載されています。
pom.xml の依存定義と、ソースコードを確認
-
pom.xml の定義
もしかしてとpom
を見たらしっかり、version1
、version2
の両方が定義されていました。
<!-- JSON API --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.7.4</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency>
-
ObjectMapper の import 定義
ObjectMapper
のimport
記述は、version1
を使用する形になっていました。
import org.codehaus.jackson.map.ObjectMapper;
-
@JsonProperty
の import 定義
@JsonProperty
のimport
記述は、version2
を使用する形になっていました。
import com.fasterxml.jackson.annotation.JsonProperty;
原因
version1
の ObjectMapper
が version2
のアノテーションを解釈できるわけはなく、知らない Field
があるよとエラーになっていたようです。
version1
は不要なので pom
上削除して import
文変更で対応しましたが、混在している場合、且つ、混在させる必要性がある場合は結構なハマるポイントになりそうに思いました。
古いライブラリの、version1 、新しいライブラリの version2 がクラスパスに存在すると、たまにやらかす間違いになりそうです。
IDE の設定で、片方をコード補完で登場しないように設定しておく等、間違い防止策は必要かと思います。
以上です。
コメント