Джексон: Что произойдет, если свойство пропало? - PullRequest
57 голосов
/ 30 ноября 2011

Что произойдет, если я аннотирую параметр конструктора, используя @JsonProperty, но Json не указывает это свойство. Какое значение получает конструктор?

Как отличить свойство со значением NULL от свойства, отсутствующего в JSON?

Ответы [ 6 ]

44 голосов
/ 26 января 2012

Обобщение отличных ответов Программист Брюс и StaxMan :

  1. Недостающим свойствам, на которые ссылается конструктор, присваивается значение по умолчанию как определено в Java .

  2. Вы можете использовать методы установки для различения свойств, которые установлены неявно или явно.Методы-установщики вызываются только для свойств с явными значениями.Методы установки могут отслеживать, было ли свойство явно установлено с использованием логического флага (например, isValueSet).

35 голосов
/ 30 ноября 2011

Что произойдет, если я аннотирую параметр конструктора, используя @JsonProperty, но Json не указывает это свойство.Какое значение получает конструктор?

Для вопросов, подобных этому, я хотел бы просто написать пример программы и посмотреть, что произойдет.

Ниже приведен пример такой программы.

import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.ObjectMapper;

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

    // {"name":"Fred","id":42}
    String jsonInput1 = "{\"name\":\"Fred\",\"id\":42}";
    Bar bar1 = mapper.readValue(jsonInput1, Bar.class);
    System.out.println(bar1);
    // output: 
    // Bar: name=Fred, id=42

    // {"name":"James"}
    String jsonInput2 = "{\"name\":\"James\"}";
    Bar bar2 = mapper.readValue(jsonInput2, Bar.class);
    System.out.println(bar2);
    // output:
    // Bar: name=James, id=0

    // {"id":7}
    String jsonInput3 = "{\"id\":7}";
    Bar bar3 = mapper.readValue(jsonInput3, Bar.class);
    System.out.println(bar3);
    // output:
    // Bar: name=null, id=7
  }
}

class Bar
{
  private String name = "BLANK";
  private int id = -1;

  Bar(@JsonProperty("name") String n, @JsonProperty("id") int i)
  {
    name = n;
    id = i;
  }

  @Override
  public String toString()
  {
    return String.format("Bar: name=%s, id=%d", name, id);
  }
}

В результате конструктору передается значение по умолчанию для типа данных.

Как отличить свойство, имеющее нулевое значение, от свойства, которого нетв JSON?

Один простой подход заключается в проверке значения по умолчанию после обработки десериализации, поскольку, если элемент присутствовал в JSON, но имел нулевое значение, тогда использовалось бы нулевое значениезаменить любое значение по умолчанию, соответствующее соответствующему полю Java.Например:

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;

public class JacksonFooToo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);

    // {"name":null,"id":99}
    String jsonInput1 = "{\"name\":null,\"id\":99}";
    BarToo barToo1 = mapper.readValue(jsonInput1, BarToo.class);
    System.out.println(barToo1);
    // output:
    // BarToo: name=null, id=99

    // {"id":99}
    String jsonInput2 = "{\"id\":99}";
    BarToo barToo2 = mapper.readValue(jsonInput2, BarToo.class);
    System.out.println(barToo2);
    // output:
    // BarToo: name=BLANK, id=99

    // Interrogate barToo1 and barToo2 for 
    // the current value of the name field.
    // If it's null, then it was null in the JSON.
    // If it's BLANK, then it was missing in the JSON.
  }
}

class BarToo
{
  String name = "BLANK";
  int id = -1;

  @Override
  public String toString()
  {
    return String.format("BarToo: name=%s, id=%d", name, id);
  }
}

Другой подход заключается в реализации пользовательского десериализатора, который проверяет необходимые элементы JSON.И еще один подход заключается в том, чтобы зарегистрировать запрос на улучшение в проекте Джексона на http://jira.codehaus.org/browse/JACKSON

12 голосов
/ 30 ноября 2011

В дополнение к поведению конструктора, описанному в ответе @ Programmer_Bruce, один из способов различить нулевое значение и пропущенное значение состоит в определении сеттера: сеттер вызывается только с явным нулевым значением.Затем пользовательский установщик может установить частный логический флаг («isValueSet» или любой другой), если вы хотите следить за установленными значениями.

Установщики имеют приоритет над полями, если существуют поле и установщик, поэтому вы можетепереопределить "поведение таким же образом.

3 голосов
/ 11 февраля 2014

Я думаю об использовании чего-либо в стиле класса Option, где объект Nothing скажет мне, есть ли такое значение или нет.Кто-нибудь делал что-то подобное с Джексоном (на Java, а не в Scala и др.)?

0 голосов
/ 25 июля 2018

другой вариант - проверка объекта после десериализации либо вручную, либо с помощью таких структур, как проверка Java-бина или, если вы используете spring, поддержка проверки пружины.

0 голосов
/ 18 мая 2017

(Мой ответ может быть полезен для некоторых людей, которые находят эту ветку в Google, даже если она не отвечает на вопросы ОП)
Если вы имеете дело с примитивными типами, которые не допускаются, и вы не хотите использовать установщик, как описано в других ответах (например, если вы хотите, чтобы ваше поле было финальным), вы можете использовать объекты box:

public class Foo {
    private final int number;
    public Foo(@JsonProperty Integer number) {
        if (number == null) {
            this.number = 42; // some default value
        } else {
            this.number = number;
        }
    }
}

это не работает, если JSON на самом деле содержит null, но может быть достаточно, если вы знаете, что он будет содержать только примитивы или отсутствует

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...