1. ホーム
  2. ジャワ

InvalidDefinitionException: 構築できない(Creatorが存在しない)

2022-02-26 10:55:55
<パス

概要

の使用を文書化する。 lombok デシリアライズの問題は、最初は lombok1.16.18 アプリケーションでは見つからず、その後、アプリケーションがlombokのグローバルバージョンを指定せず、導入された他の2者間パッケージがlombokのバージョンを上げて 1.16.20 というエラーが報告されます。この問題は発見させる必要があり、オンライン障害を引き起こす可能性が高いため、問題が発生するまで待つことはできず、事前に知っておく必要があるのです。

エラースタック

InvalidDefinitionException: Cannot construct instance of `com.fs.jackson.Address` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"id":1,"address":"address"}"; line: 1, column: 2]
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
	at Application.testSeriable(Application.java:36)
	at Application.run(Application.java:24)
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:790)
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:774)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234)
	at Application.main(Application.java:27)


質問

質問1.

A private modifier was written as a final by hand

@Data
public class AddressVO {
     final Long id;
    private String address;
}


課題 2 は Bulider クラスを使用します。

@Data
@Accessors(chain = true)
@Builder
public class Address {
    private Long id;
    private String address;
}


分析

lombokに起因する問題の解析は簡単で、コンパイルされたクラスファイルを見るだけです。
使用方法 jd-gui デコンパイラツールは

1.6.18

public class AddressByBuilder {
    private Long id;
    private String address;

    public static class AddressBuilder {
        private Long id;
        private String address;
        // omitted
    }

    @ConstructorProperties({ "id", "address" })
    AddressByBuilder(Long id, String address) {
        this.id = id;
        this.address = address;
    }
}


1.16.20

public class AddressByLombok20 {

    private Long id;
    private String address;
	// constructor
    AddressByLombok20(Long id, String address) {
        this.id = id;
        this.address = address;
    }
}



1.16.28と1.16.20を比較すると、コンストラクタが変更されていることがわかります。1.16.20ではコンストラクタの数が減っています

@ConstructorProperties({ "id", "address" })

JDK 1.6から登場

アノテーションは、コンストラクタの最初のパラメータが getX() メソッドで、2番目のパラメータが getY() メソッドで取得できることを示しています。パラメータ名は一般に実行時に利用できません。アノテーションがなければ、パラメータが getX() および getY() に対応しているか、その反対であるかを知る術はありません。

コンストラクタに @ConstructorProperties() アノテーションを使用すると、コンストラクタが GetName で検索できること、第1パラメータが getX() メソッドで取得できること、第2パラメータが getY() メソッドで取得できることを示すことができます。メソッドのパラメータ名は一般に実行時には見えないため、このアノテーションがなければ、パラメータが getX() および getY() やその周辺のメソッドに一致するかどうかを知る方法はありません。

これは明らかにlombokのアップグレードによる非互換な修正です。

誰もリファレンスレスコンストラクタを定義していないので、既存のコンストラクタを探し、ゲッター/セッター関数をマッチングさせます。

解決方法

1. mavenでlombokの固定バージョンを指定し、バージョン1.16.18を使用し、コードレベルでの変更は必要ありません。
2. クラスへのパラメータレスコンストラクタの追加

提案内容

Classes that need serialization, such as interacting with the front end, rpc calls, all add parameterless constructors for better compatibility


<イグ

参考

http://tutorials.jenkov.com/java-json/jackson-objectmapper.html#how-jackson-objectmapper-matches-json-fields-to-java-fields、その
https://www.jianshu.com/p/f826ba2dbcf9