Джексон: Что произойдет, если имущество отсутствует?
Что произойдет, если я аннотирую параметр конструктора с помощью @JsonProperty
, но Json не указывает это свойство. Какое значение получает конструктор?
Как отличить свойство, имеющее нулевое значение, от свойства, которое отсутствует в JSON?
Ответы
Ответ 1
Подводя отличные ответы Программист Брюс и StaxMan:
-
Отсутствующие свойства, на которые ссылается конструктор, присваиваются значениям по умолчанию как определено Java.
-
Вы можете использовать методы setter, чтобы различать свойства, которые неявно или явно заданы. Методы Setter вызывается только для свойств с явными значениями. Методы Setter могут отслеживать, было ли свойство явно задано с использованием булевого флага (например, isValueSet
).
Ответ 2
Что произойдет, если аннотировать параметр конструктора с помощью @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 null, then it was null in the JSON.
// If it 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
Ответ 3
В дополнение к поведению конструктора, объясненному в ответе @Programmer_Bruce, один из способов разграничения между нулевым значением и отсутствующим значением - это определение сеттера: setter вызывается только с явным значением null.
Пользовательский сеттер может затем установить частный логический флаг ( "isValueSet" или что-то еще), если вы хотите отслеживать установленные значения.
У сеттеров есть приоритет над полями, если существуют как поле, так и сеттер, поэтому вы также можете "переопределить" поведение.
Ответ 4
Я думаю использовать что-то в стиле класса Option, где объект Nothing скажет мне, есть ли такое значение или нет. Кто-нибудь сделал что-то подобное с Джексоном (в Java, а не Scala и др.)?
Ответ 5
(Мой ответ может быть полезен для некоторых людей, которые находят этот поток через google, даже если он не отвечает на вопрос OP)
Если вы имеете дело с примитивными типами, которые недоступны, и вы не хотите использовать установщик, как описано в других ответах (например, если вы хотите, чтобы ваше поле было окончательным), вы можете использовать объекты-боксы:
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
, но этого может быть достаточно, если вы знаете, что он будет содержать только примитивы или отсутствовать