Коли використовується властивість @JsonProperty і для чого вона використовується?


183

Це «держава»:

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 : function(response) {  
            if(response.State.isSet){   
                alert('success called successfully)
            }

Чи потрібна тут примітка @JsonProperty? У чому перевага його використання? Я думаю, що я можу видалити цю примітку, не викликаючи жодних побічних ефектів.

Читаючи про цю примітку на https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations Я не знаю, коли це потрібно використовувати?


Відповіді:


238

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

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

Це правильно аналізує в / від JSON:

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

1
Чи можуть змінні учасника String не бути перейменовані на їх правильний регістр, тому загальнодоступне ім'я String; стає загальнодоступним ім'ям рядка; ?
блакитно-небо

14
Так, вони можуть, але в середовищі Java, яка не відповідає стандартам кодування. Це більше стосується моєї педантичності, ніж справжнє питання кодування, але це хороший, але простий приклад реального використання @JsonPropertyанотації.
OldCurmudgeon

Чи може ця примітка використовуватись для члена типу Double? Мені просто цікаво, чи має бути Stringтип чи якийсь тип, який підтримує JSON? Може бути будь-якого типу @OldCurmudgeon?
Dreamer

3
@Dreamer Так. Тип не має значення. Це впливає лише на ім’я .
OldCurmudgeon

1
@Pavan - Це не матиме нічого спільного з називанням. Я б припустив, що ви повинні вивчити своїх сетерів.
OldCurmudgeon

44

Я думаю, що OldCurmudgeon і StaxMan є правильними, але ось одна відповідь на речення з простим прикладом для вас.

@JsonProperty (ім'я), повідомляє 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;
 }

Чи має ім'я класу збігатися з кореневим елементом JSON. Це не працює для мене.
Паван

39

добре для того, що зараз вартий ... JsonProperty ТАКОЖ використовується для визначення методів getter та setter для змінної, крім звичайної серіалізації та десеріалізації. Наприклад, припустимо, у вас є такий корисний навантаження:

{
  "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.3.0/com/fasterxml/jackson/annotation/JsonProperty.html


15

Без анотацій виведене ім’я властивості (щоб відповідати JSON) було б "встановлене", а не - як здається наміром - "isSet". Це тому, що відповідно до специфікації Java Beans, методи форми "isXxx" і "setXxx" означають, що існує логічна властивість "xxx" для управління.


1
Це правильна відповідь на конкретний випадок, наведений у питанні
Ендрю Спенсер

6

Як відомо, це все про серіалізацію та знесолення об'єкта. Припустимо, є об’єкт:

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

Серіалізація цього об'єкта:

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

Ім'я змінної безпосередньо використовується для серіалізації даних. Якщо ви збираєтесь видалити системні 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; 
}

6

Додавання JsonProperty також забезпечує безпеку у випадку, якщо хтось вирішить, що хоче змінити одне з імен властивостей, не реалізуючи відповідний клас, буде серіалізовано до об'єкта Json. Якщо вони змінить ім'я властивості, JsonProperty гарантує, що воно буде використовуватися в об'єкті Json, а не ім'я властивості.


3

На додаток до інших відповідей, @JsonPropertyанотація дуже важлива, якщо ви використовуєте @JsonCreatorанотацію в класах, у яких немає конструктора no-arg.

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": "ПЕРШИЙ"}

Виняток у потоці "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Неможливо побудувати екземпляр ClassToSerialize $ MyEnum з String value 'stringValue': значення не одне із оголошених назв екземплярів Enum: [FIRST, SECOND, THIRD]

Але після додавання @JsonPropertyпримітки до конструктора:

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

Десеріалізація успішна:

Серіалізовано: {"myEnum": "ПЕРШИЙ", "stringValue": "ABCD"}

StringValue: ABCD

MyEnum: ПЕРШИЙ


2

Окрім усіх наведених вище відповідей, не забувайте про частину документації, яка говорить

Анотація маркера, яка може бути використана для визначення нестатичного методу як "сеттера" або "getter" для логічного властивості (залежно від його підпису), або нестатичного об'єктного поля, яке буде використовуватися (серіалізоване, десеріалізоване) як логічне майно.

Якщо 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цього, тоді він трактується як звичайний гетьер, чому ви могли б коментувати таке @JsonIgnore.

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


0

Від компанії JsonProperty javadoc,

Визначає ім'я логічного властивості, тобто ім'я поля об'єкта JSON, яке використовуватиме для властивості. Якщо значення порожнє String (яке є за замовчуванням), спробуйте використовувати ім’я поля, яке коментується.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.