One of the common problem while parsing JSON in Java using Jackson API is that it fails when your JSON contains unknown properties i.e. your Java class doesn't have all the field corresponding to all JSON properties.
使用 Jackson API 在Java中解析JSON时的一个常见问题是,当JSON包含未知属性时,即Java类没有与所有JSON属性对应的所有字段时,解析失败。
Anyway, it was our fault that we didn't review code properly and allowed him to release his code into production without handling unknown files. The issue could have simply been avoided if he was familiar with Jackson library in a little bit more detail.
Jackson API provides two ways to ignore unknown fields, first at the class level using @JsonIgnoreProperties annotation and second at the ObjectMapper level using configure() method.
You will see both approaches in this article and learn how to use them and when to use @JsonIgnoreProperties and when to ignore unknown fields in JSON globally at the ObjectMapper level.
不管怎样,这是我们的错,我们没有正确地审查代码,并允许他在不处理未知文件的情况下将代码发布到生产环境中。如果他对Jackson library 更为熟悉一点,这个问题本可以简单地避免。
jackson api提 供了两种忽略未知字段的方法:
第一种是在类级别使用 @JsonIgnoreProperties 注解,
第二种是在 ObjectMapper 级别使用configure() 方法。
Ignoring unknown properties using @JsonIgnoreProperties
If you are creating a Model class to represent the JSON in Java, then you can annotate the class with @JsonIgnoreProperties(ignoreUnknown = true) to ignore any unknown field. Which means if there is a new field is added tomorrow on JSON which represent your Model then Jackson will not throw UnrecognizedPropertyException while parsing JSON in Java.
如果您正在创建一个模型类来用Java表示JSON,那么您可以用 @JsonIgnoreProperties(ignoreUnknown=true)注释该类以忽略任何未知字段。这意味着如果明天在JSON上添加了一个新的字段来表示您的模型,那么Jackson在Java中解析JSON时不会抛出UnrecognizedPropertyException。
using @JsonIgnoreProperties annotation as shown below:
Add the following to the top of your class (not to individual methods):
@JsonIgnoreProperties(ignoreUnknown = true)
public class Foo {
...
}
Depending on the jackson version you are using you would have to use a different import in the current version it is:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
in older versions it has been:
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
Ignoring Unknown Property in JSON Globally using Jackson
Another way to deal with unknown properties in JSON you are parsing is to configure ObjectMapper not to fail when it encounters an unknown property. This will also solve the problem of UnrecognizedPropertyException. You can enable this setting by calling configure() method as shown below:
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
This will now ignore unknown properties for any JSON it's going to parse, You should only use this option if you can't annotate a class with @JsonIgnoreProperties annotation.
In addition to 2 mechanisms already mentioned, there is also global feature that can be used to suppress all failures caused by unknown (unmapped) properties:
// jackson 1.9 and before
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// or jackson 2.0
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
This is the default used in absence of annotations, and can be convenient fallback.
一个完整使用 jackson 的 JsonUtil 的工具类示例
package com.bytedance.kunlun.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@Slf4j
public class JsonUtil {
public static final ObjectMapper mapper =new ObjectMapper();
static {
// 忽略未知字段
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public static String serialize(Object obj) {
if (obj ==null) {
return null;
}
if (obj.getClass() ==String.class) {
return (String) obj;
}
try {
return mapper.writeValueAsString(obj);
}catch (JsonProcessingException e) {
log.error("json序列化出错:" + obj, e);
return null;
}
}
public static T parse(String json,Class tClass) {
try {
return mapper.readValue(json, tClass);
}catch (IOException e) {
log.error("json解析出错:" + json, e);
return null;
}
}
public static ListparseList(String json,Class eClass) {
try {
return mapper.readValue(json,mapper.getTypeFactory().constructCollectionType(List.class, eClass));
}catch (IOException e) {
log.error("json解析出错:" + json, e);
return null;
}
}
public static MapparseMap(String json,Class kClass,Class vClass) {
try {
return mapper.readValue(json,mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass));
}catch (IOException e) {
log.error("json解析出错:" + json, e);
return null;
}
}
}
参考资料
Ignoring new fields on JSON objects using Jackson [duplicate]
https://www.baeldung.com/jackson-ignore-properties-on-serialization
https://www.baeldung.com/jackson-deserialize-json-unknown-properties