Когда используется свойство @JsonProperty и для чего оно используется?

#java #json

#java #ajax #джексон

Вопрос:

Этот компонент «Состояние» :

 public class State {

    private boolean isSet;

    @JsonProperty("isSet")
    public boolean isSet() {
        return isSet;
    }

    @JsonProperty("isSet")
    public void setSet(boolean isSet) {
        this.isSet = isSet;
    }

}
 

отправляется по проводу с использованием обратного вызова ajax ‘success’ :

         success : function(response) {  
            if(response.State.isSet){   
                alert('success called successfully)
            }
 

Требуется ли здесь аннотация @JsonProperty ? В чем преимущество его использования?
Я думаю, что могу удалить эту аннотацию, не вызывая никаких побочных эффектов.

Читая об этом объявлении на https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations Я не знаю, когда это необходимо использовать?

Комментарии:

1. baeldung.com/jackson-annotations

Ответ №1:

Вот хороший пример. Я использую его для переименования переменной, потому что JSON поступает из .Net среды, где свойства начинаются с заглавной буквы.

 public class Parameter {
  @JsonProperty("Name")
  public String name;
  @JsonProperty("Value")
  public String value; 
}
 

Это правильно выполняет синтаксический анализ в / из JSON:

 "Parameter":{
  "Name":"Parameter-Name",
  "Value":"Parameter-Value"
}
 

Комментарии:

1. Могут ли переменные-члены строки не быть переименованы в их правильный регистр, поэтому public String name; становится public String Name; ?

2. Да, они могут, но в среде Java, которая заставляет их не соответствовать стандартам кодирования. Это больше связано с моей педантичностью, чем с реальной проблемой кодирования, но это хороший, но простой пример реального использования @JsonProperty аннотации.

3. Можно ли использовать эту аннотацию для члена типа Double ? Мне просто интересно, должен ли быть тип String или любой тип, который поддерживает JSON? Может ли это быть любой тип?@ OldCurmudgeon

4. @Dreamer Да. Тип не имеет значения. Это влияет только на имя .

5. @Pavan — Это не будет иметь никакого отношения к именованию. Я бы предположил , что вам следует изучить свои сеттеры.

Ответ №2:

Я думаю, что OldCurmudgeon и StaxMan оба верны, но вот ответ в одном предложении с простым примером для вас.

@JsonProperty(name) сообщает Jackson ObjectMapper сопоставить имя свойства JSON с именем аннотированного поля Java.

 //example of json that is submitted 
"Car":{
  "Type":"Ferrari",
}

//where it gets mapped 
public static class Car {
  @JsonProperty("Type")
  public String type;
 }
 

Комментарии:

1. Должно ли имя класса совпадать с корневым элементом JSON. У меня это не работает.

Ответ №3:

ну, чего бы это сейчас ни стоило… JsonProperty ТАКЖЕ используется для указания методов получения и установки для переменной, помимо обычной сериализации и десериализации. Например, предположим, что у вас есть такая полезная нагрузка:

 {
  "check": true
}
 

и класс десериализатора:

 public class Check {

  @JsonProperty("check")    // It is needed else Jackson will look got getCheck method and will fail
  private Boolean check;

  public Boolean isCheck() {
     return check;
  }
}
 

Тогда в этом случае не нужна аннотация JsonProperty. Однако, если у вас также есть метод в классе

 public class Check {

  //@JsonProperty("check")    Not needed anymore
  private Boolean check;

  public Boolean getCheck() {
     return check;
  }
}
 

Также взгляните на эту документацию:
http://fasterxml.github.io/jackson-annotations/javadoc/2.13/com/fasterxml/jackson/annotation/JsonProperty.html

Ответ №4:

Без аннотаций выведенное имя свойства (для сопоставления с JSON) будет «установлено», а не — как кажется намерением — «isSet». Это связано с тем, что в соответствии со спецификацией Java Beans методы формы «isXXX» и «setXXX» подразумевают, что существует логическое свойство «xxx» для управления.

Комментарии:

1. Это правильный ответ для конкретного случая, указанного в вопросе

Ответ №5:

Добавление JsonProperty также обеспечивает безопасность на случай, если кто-то решит, что хочет изменить одно из имен свойств, не понимая, что рассматриваемый класс будет сериализован в объект Json. Если они изменяют имя свойства, JsonProperty гарантирует, что оно будет использоваться в объекте Json, а не в имени свойства.

Ответ №6:

Как вы знаете, все это касается сериализации и десалинизации объекта. Предположим, что существует объект:

 public class Parameter {
  public String _name;
  public String _value; 
}
 

Сериализация этого объекта:

 {
  "_name": "...",
  "_value": "..."
}
 

Имя переменной напрямую используется для сериализации данных. Если вы собираетесь удалить system api из системной реализации, в некоторых случаях вам необходимо переименовать переменную в сериализации / десериализации. @JsonProperty — это метаданные, которые сообщают сериализатору, как выполнить последовательный объект. Оно используется для:

  • имя переменной
  • доступ (ЧТЕНИЕ, ЗАПИСЬ)
  • значение по умолчанию
  • обязательно / необязательно

из примера:

 public class Parameter {
  @JsonProperty(
        value="Name",
        required=true,
        defaultValue="No name",
        access= Access.READ_WRITE)
  public String _name;
  @JsonProperty(
        value="Value",
        required=true,
        defaultValue="Empty",
        access= Access.READ_WRITE)
  public String _value; 
}
 

Ответ №7:

В дополнение ко всем приведенным выше ответам не забудьте часть документации, в которой говорится

Аннотация маркера, которая может использоваться для определения нестатического метода как «установщика» или «получателя» для логического свойства (в зависимости от его сигнатуры) или нестатического поля объекта, которое будет использоваться (сериализовано, десериализовано) в качестве логического свойства.

Если non-static в вашем классе есть метод, который не является обычным getter or setter , вы можете заставить его действовать как a getter and setter , используя аннотацию к нему. Смотрите пример ниже

 public class Testing {
    private Integer id;
    private String username;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getIdAndUsername() {
        return id   "."   username; 
    }

    public String concatenateIdAndUsername() {
        return id   "."   username; 
    }
}
 

Когда указанный выше объект сериализуется, ответ будет содержать

  • имя пользователя из getUsername()
  • идентификатор из getId()
  • idAndUsername из getIdAndUsername *

Поскольку метод getIdAndUsername начинается с get then, он обрабатывается как обычный геттер, следовательно, почему вы могли бы аннотировать его с @JsonIgnore помощью .

Если вы заметили concatenateIdAndUsername , что не возвращается, и это потому, что его имя не начинается с get , и если вы хотите, чтобы результат этого метода был включен в ответ, тогда вы можете использовать @JsonProperty("...") , и он будет рассматриваться как обычный getter/setter , как указано в выделенной выше документации.

Ответ №8:

В дополнение к другим ответам @JsonProperty аннотация действительно важна, если вы используете @JsonCreator аннотацию в классах, у которых нет конструктора без аргументов.

 public class ClassToSerialize {

    public enum MyEnum {
        FIRST,SECOND,THIRD
    }

    public String stringValue = "ABCD";
    public MyEnum myEnum;


    @JsonCreator
    public ClassToSerialize(MyEnum myEnum) {
        this.myEnum = myEnum;
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        ClassToSerialize classToSerialize = new ClassToSerialize(MyEnum.FIRST);
        String jsonString = mapper.writeValueAsString(classToSerialize);
        System.out.println(jsonString);
        ClassToSerialize deserialized = mapper.readValue(jsonString, ClassToSerialize.class);
        System.out.println("StringValue: "   deserialized.stringValue);
        System.out.println("MyEnum: "   deserialized.myEnum);
    }
}
 

В этом примере единственный конструктор помечен как @JsonCreator , поэтому Джексон будет использовать этот конструктор для создания экземпляра. Но результат выглядит так:

Сериализованный: {«stringValue»:»ABCD»,»MyEnum»:»FIRST»}

Исключение в потоке «main» com.fasterxml.jackson.databind.exc.InvalidFormatException: невозможно создать экземпляр classstoserialize$MyEnum из строкового значения ‘stringValue’: значение, не являющееся одним из объявленных имен экземпляров Enum: [ПЕРВОЕ, ВТОРОЕ, ТРЕТЬЕ]

Но после добавления @JsonProperty аннотации в конструктор:

 @JsonCreator
public ClassToSerialize(@JsonProperty("myEnum") MyEnum myEnum) {
    this.myEnum = myEnum;
}
 

Десериализация выполнена успешно:

Сериализованный: {«MyEnum»:»FIRST»,»stringValue»:»ABCD»}

Строковое значение: ABCD

MyEnum: СНАЧАЛА

Ответ №9:

Из JsonProperty javadoc,

Определяет имя логического свойства, то есть имя поля объекта JSON, которое будет использоваться для свойства. Если значение является пустой строкой (которая используется по умолчанию), попытается использовать имя поля, которое аннотируется.