com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from...


エラー

Jackson で、ObjectMapper を使用して、以下のように mapper#readValue() したところ、エラーが発生しました。

  • 実装記述

        ObjectMapper mapper = new ObjectMapper();
        Show show = mapper.readValue(json, Show.class);
    

  • エラー内容

    (through reference chain: xyz.monotalk.social.mixcloud.data.Show["tags"]->java.util.ArrayList[0]->xyz.monotalk.social.mixcloud.data.Tag["type"])
                at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:51)
                at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:817)
                at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:980)
                at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1324)
                at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1302)
                at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:249)
                at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
    


原因と、解決方法

JSON 連想配列にある項目が Java データクラスに定義されていないため、エラーが発生していました。

フィールドを追加して、エラーを解決する

  • 修正前のデータクラスの記述

    /**
     * Show
     *
     * @author Kem
     */
    @Getter
    @Setter
    @AllArgsConstructor
    @Builder
    @ToString
    public class Show extends Response {
    
        public Show() {
            super();
        }
    
        private String description;
    }
    

  • 修正後のデータクラスの記述
    private String type; を追加することで、エラーは解消されます。

    /**
     * Show
     *
     * @author Kem
     */
    @Getter
    @Setter
    @AllArgsConstructor
    @Builder
    @ToString
    public class Show extends Response {
    
        public Show() {
            super();
        }
    
        private String description;
        private String type;
    
    }
    

フィールドを無視してエラーにならないようにする

jacksonを使ってjsonをデシリアライズする
に記載がありますが、以下のアノテーションを付与することで、存在しないフィールドを無視することができます。

   JsonIgnoreProperties(ignoreUnknown=true)

JsonAnyGetter で 想定できないフィールドを Map に設定する

以下 が参考になりました。
JacksonHowToIgnoreUnknown · FasterXML/jackson-docs Wiki
jacksonで正体不明のJSONを読み込む - Qiita

JsonAnyGetterJsonAnySetter アノテーションを使って、予期しないフィールドの設定処理、取得処理の実装ができます。


どの方法で解決するか

外部公開サービスの場合、IFの変更のコントロールが難しいので、@JsonIgnoreProperties を使用するか、JsonAnyGetterJsonAnySetter で拡張属性に設定しておくのが、無難に思いました。
突如追加されるフィールドを登録して使用することはほぼなさそうに思いますので、@JsonIgnoreProperties で無視しておいて、必要になったら、フィールド定義して明示的に取得するのがよいかと思います。
以上です。

コメント