web-dev-qa-db-ja.com

コンストラクターに@JsonCreatorアノテーションが付けられている場合、その引数に@JsonPropertyアノテーションが必要なのはなぜですか?

ジャクソンでは、@JsonCreatorでコンストラクタに注釈を付けるとき、@JsonPropertyで引数に注釈を付ける必要があります。このコンストラクタ

public Point(double x, double y) {
    this.x = x;
    this.y = y;
}

これになります:

@JsonCreator
public Point(@JsonProperty("x") double x, @JsonProperty("y") double y) {
    this.x = x;
    this.y = y;
}

なぜ必要なのか分かりません。説明してもらえますか?

88
Ori Popowski

ジャクソンは、JSONオブジェクトからコンストラクターにフィールドを渡す順序を知る必要があります。リフレクションを使用してJavaのパラメーター名にアクセスすることはできません。そのため、この情報を注釈で繰り返す必要があります。

95
Lukasz Wiktor

パラメーター名は通常、実行時にJavaコードからアクセスできません(コンパイラーによってドロップされるため)。したがって、その機能が必要な場合は、Java 8の組み込み機能を使用する必要があります。または、ParaNamerなどのライブラリを使用してアクセスします。

そのため、Jacksonを使用するときにコンストラクター引数に注釈を使用する必要がないように、次の2つのJacksonモジュールのいずれかを使用できます。

jackson-module-parameter-names

このモジュールを使用すると、Java 8を使用するときに注釈のないコンストラクター引数を取得できます。それを使用するには、最初にモジュールを登録する必要があります。

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ParameterNamesModule());

次に、-parametersフラグを使用してコードをコンパイルします。

javac -parameters ...

リンク: https://github.com/FasterXML/jackson-modules-Java8/tree/master/parameter-names

jackson-module-paranamer

このもう1つの方法では、モジュールを登録するか、注釈のイントロスペクションを構成する必要があります(ただし、コメントで指摘されているとおりではありません)。 1.8の前のJavaのバージョンで注釈のないコンストラクター引数を使用できます。

ObjectMapper mapper = new ObjectMapper();
// either via module
mapper.registerModule(new ParanamerModule());
// or by directly assigning annotation introspector (but not both!)
mapper.setAnnotationIntrospector(new ParanamerOnJacksonAnnotationIntrospector());

リンク: https://github.com/FasterXML/jackson-modules-base/tree/master/paranamer

45
Rodrigo Quesada

オプションで、コンパイラーがコンストラクター・パラメーターの名前を持つメタデータを導入するjdk8では、コンストラクターの注釈を避けることができます。次に、 jackson-module-parameter-names モジュールを使用すると、Jacksonはこのコンストラクターを使用できます。投稿で例を見ることができます 注釈のないジャクソン

23

Javaバイトコードはメソッド名またはコンストラクター引数の名前を保持しないためです。

6
lcfd

this を正しく理解すると、デフォルトのコンストラクターをパラメーター化されたコンストラクターに置き換えるため、コンストラクターの呼び出しに使用されるJSONキーを記述する必要があります。

4
Smutje

注釈ドキュメント で詳しく説明されているように、注釈は引数名が変更なしでプロパティ名として使用されることを示しますが、異なる名前を指定するために空でない値に指定できます。

3
Guy Bouallet

Java.bean.ConstructorProperties注釈を使用するだけで済みます-冗長性ははるかに低く、ジャクソンも受け入れます。例えば ​​:

  import Java.beans.ConstructorProperties;

  @ConstructorProperties({"answer","closed","language","interface","operation"})
  public DialogueOutput(String answer, boolean closed, String language, String anInterface, String operation) {
    this.answer = answer;
    this.closed = closed;
    this.language = language;
    this.anInterface = anInterface;
    this.operation = operation;
  }
1
letowianka