コンストラクタに@JsonCreatorの注釈が付けられている場合、その引数に@JsonPropertyの注釈が付けられる必要があるのはなぜですか?


108

ジャクソンでは、コンストラクターにで注釈を付ける場合@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;
}

なぜ必要なのか分かりません。説明していただけますか?

回答:


112

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


9
これはJava8には無効です
MariuszS

12
@MariuszSそのとおりですが、この投稿では、Java8コンパイラフラグとJacksonモジュールを使用して、無関係な注釈を取り除く方法を説明しています。私はアプローチをテストしましたが、うまくいきました。
クォンタム

魔法のように勿論、作品:) docs.oracle.com/javase/tutorial/reflect/member/...
MariuszS

52

パラメータ名は通常、実行時に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.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


28

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



6

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



1
@MariuszSは確かですが、これは新しい(デフォルトではないコンパイラフラグです)ため、Jacksonは引き続き@JsonPropertyアノテーションをサポートする必要があります
lcfd

6

単純にjava.bean.ConstructorPropertiesアノテーションを使用できます。これはそれほど冗長ではなく、Jacksonもそれを受け入れます。例えば ​​:

  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;
  }

4

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



0

ちょうどそれに遭遇し、どこかで答えを得ました。2.7.0以降、以下のアノテーションを使用できます

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class Point {
    final private double x;
    final private double y;

    @ConstructorProperties({"x", "y"})
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.