Jackson 反序列化包含未知属性的 JSON
最后更新:2021年12月8日
1. 概述
在本教程中,我们将探讨使用 Jackson 2.x 的反序列化过程,特别是如何处理包含未知属性的 JSON 内容。
要深入了解并学习我们可以使用 Jackson 做的其他很酷的事情,我们可以查看 主要的 Jackson 教程。
更多阅读
2. 反序列化带有附加/未知字段的 JSON
JSON 输入有各种形状和大小,大多数时候,我们需要将其映射到具有固定数量字段的预定义 Java 对象。 目标是简单地忽略无法映射到现有 Java 字段的任何 JSON 属性。
例如,假设我们需要将 JSON 反序列化到以下 Java 实体
public class MyDto {
private String stringValue;
private int intValue;
private boolean booleanValue;
// standard constructor, getters and setters
}
2.1. 未知字段上的 UnrecognizedPropertyException
尝试将带有未知属性的 JSON 反序列化到这个简单的 Java 实体会导致com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException
@Test(expected = UnrecognizedPropertyException.class)
public void givenJsonHasUnknownValues_whenDeserializingAJsonToAClass_thenExceptionIsThrown()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString =
"{\"stringValue\":\"a\"," +
"\"intValue\":1," +
"\"booleanValue\":true," +
"\"stringValue2\":\"something\"}";
ObjectMapper mapper = new ObjectMapper();
MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
assertNotNull(readValue);
}
这将出现以下异常
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
Unrecognized field "stringValue2" (class org.baeldung.jackson.ignore.MyDto),
not marked as ignorable (3 known properties: "stringValue", "booleanValue", "intValue"])
2.2. 使用 ObjectMapper 处理未知字段
我们现在可以配置完整的 ObjectMapper 来忽略 JSON 中的未知属性
new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
然后我们应该能够将这种 JSON 读取到预定义的 Java 实体中
@Test
public void givenJsonHasUnknownValuesButJacksonIsIgnoringUnknownFields_whenDeserializing_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString =
"{\"stringValue\":\"a\"," +
"\"intValue\":1," +
"\"booleanValue\":true," +
"\"stringValue2\":\"something\"}";
ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo("a"));
assertThat(readValue.isBooleanValue(), equalTo(true));
assertThat(readValue.getIntValue(), equalTo(1));
}
2.3. 在类级别处理未知字段
我们还可以将单个类标记为接受未知字段,而不是整个 Jackson ObjectMapper
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyDtoIgnoreUnknown { ... }
现在我们应该能够测试与之前相同的行为。 未知字段将被简单地忽略,并且仅映射已知字段
@Test
public void givenJsonHasUnknownValuesButUnknownFieldsAreIgnoredOnClass_whenDeserializing_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString =
"{\"stringValue\":\"a\"," +
"\"intValue\":1," +
"\"booleanValue\":true," +
"\"stringValue2\":\"something\"}";
ObjectMapper mapper = new ObjectMapper();
MyDtoIgnoreUnknown readValue = mapper
.readValue(jsonAsString, MyDtoIgnoreUnknown.class);
assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo("a"));
assertThat(readValue.isBooleanValue(), equalTo(true));
assertThat(readValue.getIntValue(), equalTo(1));
}
3. 反序列化不完整的 JSON
与附加的未知字段类似,反序列化不完整的 JSON,即不包含 Java 类中所有字段的 JSON,对于 Jackson 来说不是问题
@Test
public void givenNotAllFieldsHaveValuesInJson_whenDeserializingAJsonToAClass_thenCorrect()
throws JsonParseException, JsonMappingException, IOException {
String jsonAsString = "{"stringValue":"a","booleanValue":true}";
ObjectMapper mapper = new ObjectMapper();
MyDto readValue = mapper.readValue(jsonAsString, MyDto.class);
assertNotNull(readValue);
assertThat(readValue.getStringValue(), equalTo("a"));
assertThat(readValue.isBooleanValue(), equalTo(true));
}
4. 结论
在本文中,我们讨论了使用 Jackson 反序列化具有附加未知属性的 JSON。
这是在使用 Jackson 时最常见的配置之一,因为我们通常需要将外部 REST API 的 JSON 结果映射到 API 实体的内部 Java 表示形式。
支持本文的代码可在 GitHub 上获取。 一旦你以 Baeldung Pro 会员 身份登录,就开始学习并在项目上进行编码。















