1. 概述
在这个教程中,我们将探讨在使用 Jackson 解析JSON字符串时处理null
或缺失值的不同方法。我们将深入研究三种提供不同控制级别的选项。
2. 在类级别设置默认值
首先,我们来看如何在接收的JSON字符串中完全缺失字段时,将默认值放入我们的POJO(Plain Old Java Object)对象。创建一个有两个字段的对象,其中一个为必需,另一个我们将设置默认值:
class NonAnnotatedDefaultValue {
String required;
String optional = "defaultValue";
// Standard getters and setters
}
这里我们在名为optional
的字段上分配了一个值。如果JSON中没有这个字段,Jackson将使用这个String
值。现在,让我们使用这个对象,让Jackson将一个不包含名为optional
字段的JSON字符串映射到对象。我们将使用[ObjectMapper](/jackson-object-mapper-tutorial)
对象及其readValue()
方法:
@Test
void givenAClassWithADefaultValue_whenReadingJsonWithoutOptionalValue_thenExpectDefaultValueInResult()
throws JsonProcessingException {
String noOptionalField = "{\"required\": \"value\"}";
ObjectMapper objectMapper = new ObjectMapper();
NonAnnotatedDefaultValue createdObject = objectMapper.readValue(noOptionalField, NonAnnotatedDefaultValue.class);
assert(createdObject.getRequired()).equals("value");
assert(createdObject.getOptional()).equals("defaultValue");
}
通过断言,我们可以看到生成的对象既包含了JSON中的值,也包含了我们之前指定的默认值。
这种方法的缺点是,它只适用于JSON中的属性完全缺失的情况。 如果属性存在但值为null
,Jackson将不会应用默认值。在接下来的部分,我们将看到更佳的方法来处理null
值。
3. 实现setter方法以获取最大控制权
我们可以通过为字段实现setter方法来完全控制映射过程。创建一个具有Jackson用于创建对象所需的必需setter的方法的对象:
class SetterDefaultValue {
String required;
String optional = "valueIfMissingEntirely";
public void setOptional(String optional) {
if (optional == null) {
this.optional = "valueIfNull";
}
}
// Standard getters and setters
}
这里我们像以前一样在类级别提供了默认值。然而,我们也提供了setter方法。在setter方法内部,我们现在可以执行任何我们喜欢的操作。在这个例子中,我们明确地提供了当值为null
时的预期行为。现在,如果我们不在JSON中包含该属性,Jackson将设置optional
为valueIfMissingEntirely
,如果属性存在但设置为null
,则设置为valueIfNull
。
如果我们需要,这两个值可以相同。让我们看看实际操作:
@Test
void givenAClassWithASetter_whenReadingJsonWithNullOptionalValue_thenExpectDefaultValueInResult()
throws JsonProcessingException {
String nullOptionalField = "{\"required\": \"value\", \"optional\": null}";
ObjectMapper objectMapper = new ObjectMapper();
JsonSetterDefaultValue createdObject = objectMapper.readValue(nullOptionalField, JsonSetterDefaultValue.class);
assert(createdObject.getRequired()).equals("value");
assert(createdObject.getOptional()).equals("valueIfNull");
}
这里我们提供了JSON,其中名为optional
的字段被设置为null
。从断言中我们可以看出,Jackson创建的对象中,由于我们的注解,optional
字段已设置为valueIfNull
。这种方法为我们提供了极大的灵活性。如果我们想要,我们也可以检查空String
并以相同的方式应用默认值。
4. 使用@JsonSetter与Nulls.SKIP
我们的最后一个选项是使用@JsonSetter
并将其扩展以告诉它忽略null
值。让我们创建一个新的类:
class NullsSkipDefaultValue {
private String required;
@JsonSetter(nulls = Nulls.SKIP)
private String optional = "defaultValue";
// standard getters and setters
}
Nulls.SKIP
参数告诉@JsonSetter
跳过所有null
值的输入。然后Jackson将使用提供的默认值。Nulls枚举中还有其他几个选项,例如Nulls.SET
会告诉Jackson将JSON中的null
转换为POJO中的Java null
。今天我们将继续使用Nulls.SKIP
:
@Test
void givenAClassWithAJsonSetterNullsSkip_whenReadingJsonWithNullOptionalValue_thenExpectDefaultValueInResult() throws JsonProcessingException {
String nullOptionalField = "{\"required\": \"value\", \"optional\": null}";
ObjectMapper objectMapper = new ObjectMapper();
NullsSkipDefaultValue createdObject = objectMapper.readValue(nullOptionalField, NullsSkipDefaultValue.class);
assert(createdObject.getRequired()).equals("value");
assert(createdObject.getOptional()).equals("defaultValue");
}
如上所述,对于第3部分中的相同输入JSON(即optional
字段被赋值为null
),我们得到了我们想要的默认值。如果我们不提供可选字段,这也给出了相同的结果。
5. 总结
在这篇文章中,我们探讨了使用Jackson解析JSON时处理缺失或null
值的三种方法。类级别设置值很有用,但如果遇到null
值则会失败。我们可以选择实现setter方法以获得最大控制,或者在字段声明上使用@JsonSetter
来简单地忽略null
值。这三种方法根据我们的具体需求都可能是合适的。最重要的是考虑我们希望应用程序如何处理值为null
的属性。
如往常一样,示例的完整代码可以在GitHub上找到。