Java 杰克逊:如果财产丢失怎么办?
如果我使用Java 杰克逊:如果财产丢失怎么办?,java,jackson,Java,Jackson,如果我使用@JsonProperty注释构造函数参数,但Json没有指定该属性,会发生什么。构造函数得到什么值 如何区分具有空值的属性和JSON中不存在的属性 如果我使用@JsonProperty注释构造函数参数,但Json没有指定该属性,会发生什么。构造函数得到什么值 对于这样的问题,我只想编写一个示例程序,看看会发生什么 下面是这样一个示例程序 import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jac
@JsonProperty
注释构造函数参数,但Json没有指定该属性,会发生什么。构造函数得到什么值
如何区分具有空值的属性和JSON中不存在的属性
如果我使用@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元素。还有另一种方法是将Jackson项目的增强请求记录在上。除了@Programmer\u Bruce的回答中解释的构造函数行为之外,区分空值和缺少值的一种方法是定义一个setter:setter只使用显式空值调用。 如果您希望跟踪设置的值,则自定义setter可以设置一个私有布尔标志(“isValueSet”或其他内容)
如果字段和setter都存在,setter优先于字段,因此您也可以通过这种方式“重写”行为。总结和的优秀答案:
isValueSet
)显式设置了属性我正在考虑使用Option类的样式,其中Nothing对象会告诉我是否存在这样的值。有人对Jackson做过类似的事情吗(用Java,而不是Scala等)?(我的回答可能对一些人通过谷歌找到这条线索很有用,即使它没有回答OPs问题)
如果您处理的是可忽略的基本类型,并且不希望使用其他答案中所述的setter(例如,如果希望字段为final),则可以使用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
,这就不起作用了,但是如果您知道它只包含原语或不存在,那么这就足够了。另一个选项是手动或通过java bean验证等框架在反序列化后验证对象,或者如果您使用spring,spring验证支持。“证据就在布丁中”。我同意,还有什么比尝试更好的学习方法。该项目链接已失效。有关实现自定义反序列化程序的任何信息,可以检查不存在的属性并根据预期类型指定默认值?此方法的问题是,您必须使用布尔数据类型,因为我们无法为问题设置除true或false>之外的随机值像这样,我只想写一个示例程序,看看会发生什么这并不总是一个好主意,例如,在文档中,库的当前行为可能会显式标记为不稳定。如果可能的话,最好检查文档。假设您使用同一个类进行序列化和反序列化。如果isValueSet
为false,如何告诉序列化程序忽略属性value
?这需要自定义序列化程序,无法指定排序保护标志。虽然可以使用基于注释的方法实现这样一个扩展,但相关问题:我使用Guava的Optional
作为可选属性。如果JSON中缺少该字段,则不会分配该属性。我通过使用Optional.缺席()
初始化字段解决了这个问题,但这意味着我不能使用final
字段,这有点限制。这不起作用。它不允许您区分具有空值的属性和JSON中不存在的属性。我认为,如果域/dto中的字段可以为空,那么这并不重要,缺少的JSON字段和具有空值的当前JSON字段都将转换为空域字段。如果域字段不可为null,那么验证将捕获缺少json字段的两种情况,并使用null值呈现json。您可能还想使用@jsonignoreproperties(ignoreunknown)来检测/失败遇到未知的json字段。我以前实现过一个REST API,其中未指定的可选属性被分配了一个默认值,但显式设置为null
的字段被相应地验证(例如,将null
分配给布尔属性会导致错误)。类似地,空字符串并不等同于字符串的默认值。关键是要避免验证用户可以传递并逐字解释其输入的每一个可能的疯狂值。这样就没有什么意外了。