Джексон: что произойдет, если свойство отсутствует?
что произойдет, если я аннотирую параметр конструктора с помощью @JsonProperty
но Json не указывает это свойство. Какое значение получает конструктор?
Как я могу отличить свойство, имеющее нулевое значение, от свойства, которое отсутствует в JSON?
6 ответов:
подведение итогов отличные ответы на Программист Брюс и StaxMan:
свойства, на которые ссылается конструктор присваивается значение по умолчанию как определено Java.
вы можете использовать методы setter для различения свойств, которые неявно или явно заданы. Сеттер методы вызываются только для свойств с явными значениями. Методы сеттера могут отслеживать ли свойство было явно задано с помощью логического флага (например,
isValueSet
).
что произойдет, если я аннотирую параметр конструктора с помощью @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
в дополнение к поведению конструктора, описанному в ответе @Programmer_Bruce, один из способов различить нулевое значение и отсутствующее значение-определить сеттер: сеттер вызывается только с явным нулевым значением. Пользовательский сеттер может затем установить частный логический флаг ("isValueSet" или что-то еще), если вы хотите отслеживать набор значений.
сеттеры имеют приоритет над полями, если существуют как поле, так и сеттер, поэтому вы можете "переопределить" поведение таким образом.
Я думаю использовать что-то в стиле класса Option, где объект Nothing скажет мне, есть ли такое значение или нет. Кто-нибудь делал что-то подобное с Джексоном (на Java, а не на Scala и др.)?
(мой ответ может быть полезен некоторым людям, которые находят эту тему через google, даже если он не отвечает на вопрос OPs)
Если вы имеете дело с примитивными типами, которые опущены, и вы не хотите использовать сеттер, как описано в других ответах (например, если вы хотите, чтобы ваше поле было окончательным), вы можете использовать объекты 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
, но этого может быть достаточно, если вы знаете, что он будет содержать только примитивы или отсутствует