Por que quando um construtor é anotado com @JsonCreator, seus argumentos devem ser anotados com @JsonProperty?


108

Em Jackson, quando você anota um construtor com @JsonCreator, você deve anotar seus argumentos com @JsonProperty. Então, este construtor

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

torna-se isto:

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

Não entendo porque é necessário. Você pode explicar, por favor?

Respostas:


112

Jackson precisa saber em que ordem passar os campos de um objeto JSON para o construtor. Não é possível acessar nomes de parâmetros em Java usando reflexão - é por isso que você deve repetir essas informações nas anotações.


9
Isso não é válido para Java8
MariuszS

12
@MariuszS Isso é verdade, mas este post explica como se livrar de anotações estranhas com a ajuda do sinalizador do compilador Java8 e um módulo Jackson. Eu testei a abordagem e funciona.
quantum de

Claro, funciona como um encanto :) docs.oracle.com/javase/tutorial/reflect/member/…
MariuszS

52

Nomes de parâmetros normalmente não são acessíveis pelo código Java em tempo de execução (porque são descartados pelo compilador), então se você quiser essa funcionalidade, você precisa usar a funcionalidade integrada do Java 8 ou usar uma biblioteca como ParaNamer para obter acesso para isso.

Portanto, para não ter que utilizar anotações para os argumentos do construtor ao usar Jackson, você pode fazer uso de um destes dois módulos Jackson:

jackson-module-parameter-names

Este módulo permite que você obtenha argumentos de construtor sem anotação ao usar Java 8 . Para usá-lo, você primeiro precisa registrar o módulo:

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

Em seguida, compile seu código usando a sinalização -parameters:

javac -parameters ...

Link: https://github.com/FasterXML/jackson-modules-java8/tree/master/parameter-names

jackson-module-paranamer

Este outro simplesmente requer que você registre o módulo ou configure uma introspecção de anotação (mas não ambos como apontado pelos comentários). Ele permite que você use argumentos de construtor sem anotação em versões de Java anteriores a 1.8 .

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

Link: https://github.com/FasterXML/jackson-modules-base/tree/master/paranamer




6

Pode-se simplesmente usar a anotação java.bean.ConstructorProperties - é muito menos prolixa e Jackson também a aceita. Por exemplo :

  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

Quando eu entendi isso corretamente, você substitui o construtor padrão por um parametrizado e, portanto, tem que descrever as chaves JSON que são usadas para chamar o construtor com.


3

Conforme especificado na documentação da anotação , a anotação indica que o nome do argumento é usado como o nome da propriedade sem nenhuma modificação, mas pode ser especificado como um valor não vazio para especificar um nome diferente:


0

Basta encontrar e obter uma resposta em algum lugar. você pode usar a anotação abaixo desde 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;
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.