この記事で伝えたいこと

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 の設定で、片方をコード補完で登場しないように設定しておく等、間違い防止策は必要かと思います。
以上です。

コメント