31

私はしばらくの間、プロジェクトで FasterXML/Jackson-Databind を使用してきましたが、この投稿を発見し、このアプローチを使用して @JsonProperty アノテーションなしでオブジェクトを逆シリアル化するまで、すべてがうまく機能していました。

問題は、複数のパラメーターを取り、このコンストラクターを @JsonCreator アノテーションで装飾するコンストラクターがある場合、Jackson が次のエラーをスローすることです。

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: 
Argument #0 of constructor [constructor for com.eliti.model.Cruiser, annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
 at [Source: {
  "class" : "com.eliti.model.Cruiser",
  "inventor" : "afoaisf",
  "type" : "MeansTransport",
  "capacity" : 123,
  "maxSpeed" : 100
}; line: 1, column: 1]

問題を説明するために小さなプロジェクトを作成しました。逆シリアル化しようとしているクラスは次のとおりです。

public class Cruise extends WaterVehicle {

 private Integer maxSpeed;

  @JsonCreator
  public Cruise(String name, Integer maxSpeed) {
    super(name);
    System.out.println("Cruise.Cruise");
    this.maxSpeed = maxSpeed;
  }

  public Integer getMaxSpeed() {
    return maxSpeed;
  }

  public void setMaxSpeed(Integer maxSpeed) {
    this.maxSpeed = maxSpeed;
  }

}

デシリアライズするコードは次のようになります。

public class Test {
  public static void main(String[] args) throws IOException {
    Cruise cruise = new Cruise("asd", 100);
    cruise.setMaxSpeed(100);
    cruise.setCapacity(123);
    cruise.setInventor("afoaisf");

    ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
    mapper.registerModule(new ParameterNamesModule(JsonCreator.Mode.PROPERTIES));

    String cruiseJson = mapper.writeValueAsString(cruise);

    System.out.println(cruiseJson);

    System.out.println(mapper.readValue(cruiseJson, Cruise.class));

}

すでに @JsonCreator を削除しようとしましたが、削除すると、次の例外がスローされます。

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.eliti.model.Cruise: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
 at [Source: {
  "class" : "com.eliti.model.Cruise",
  "inventor" : "afoaisf",
  "type" : "MeansTransport",
  "capacity" : 123,
  "maxSpeed" : 100
}; line: 3, column: 3]

「mvn clean install」を実行しようとしましたが、問題が解決しません。

いくつかの追加情報を含めるために、この問題について徹底的に調査しました (GitHub の問題、ブログ投稿、StackOverflow Q&A)。私が最後に行ったデバッグ/調査は次のとおりです。

調査1

生成されたバイトコードでjavap -vを実行すると、次のようになります。

 MethodParameters:
      Name                           Flags
      name
      maxSpeed

コンストラクターについて話すとき、-parametersフラグが本当に javac コンパイラー用に設定されていると思います。

調査2

単一のパラメーターを持つコンストラクターを作成すると、オブジェクトは初期化されますが、複数のパラメーターのコンストラクターを使用したい/使用する必要があります。

調査3

各フィールドで注釈 @JsonProperty を使用しても同様に機能しますが、元のプロジェクトでは、コンストラクターに多くのフィールドがあるため、オーバーヘッドが大きすぎます (また、注釈を使用してコードをリファクタリングするのが非常に難しくなります)。

残っている問題は 、Jackson を注釈なしで複数のパラメーター コンストラクターと連携させるにはどうすればよいかということです。

4