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