有道无术,术尚可求,有术无道,止于术。
本系列Jackson 版本 2.17.0
源码地址:https://gitee.com/pearl-organization/study-jaskson-demo
文章目录
- 1. 前言
- 2. 值处理
- 2.1 USE_BIG_DECIMAL_FOR_FLOATS
- 2.2 USE_BIG_INTEGER_FOR_INTS
- 2.3 USE_LONG_FOR_INTS
- 2.4 USE_JAVA_ARRAY_FOR_JSON_ARRAY
- 3. 错误处理
- 3.1 FAIL_ON_UNKNOWN_PROPERTIES
- 3.2 FAIL_ON_NULL_FOR_PRIMITIVES
- 3.3 FAIL_ON_NUMBERS_FOR_ENUMS
- 3.4 FAIL_ON_INVALID_SUBTYPE
- 3.5 FAIL_ON_READING_DUP_TREE_KEY
- 3.6 FAIL_ON_IGNORED_PROPERTIES
- 3.7 FAIL_ON_UNRESOLVED_OBJECT_IDS
- 3.8 FAIL_ON_MISSING_CREATOR_PROPERTIES
- 3.9 FAIL_ON_NULL_CREATOR_PROPERTIES
- 3.10 FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY
- 3.11 FAIL_ON_TRAILING_TOKENS
- 3.12 WRAP_EXCEPTIONS
- 3.13 FAIL_ON_UNEXPECTED_VIEW_PROPERTIES
- 4. 结构转换
- 4.1 ACCEPT_SINGLE_VALUE_AS_ARRAY
- 4.2 UNWRAP_SINGLE_VALUE_ARRAYS
- 4.3 UNWRAP_ROOT_VALUE
- 5. 值转换
- 5.1 ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
- 5.2 ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT
- 5.3 ACCEPT_FLOAT_AS_INT
- 5.4 READ_ENUMS_USING_TO_STRING
- 5.5 READ_UNKNOWN_ENUM_VALUES_AS_NULL
- 5.6 READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE
- 5.7 READ_DATE_TIMESTAMPS_AS_NANOSECONDS
- 5.8 ADJUST_DATES_TO_CONTEXT_TIME_ZONE
- 6. 其他
- 6.1 EAGER_DESERIALIZER_FETCH
1. 前言
接下来,我们分类介绍DeserializationFeature
提供的所有特征枚举。DeserializationFeature
用于定义了一组影响JSON
文本反序列化方式的特性,这些特性既可以通过ObjectMapper
设置(作为默认值),也可以通过ObjectReader
设置。
2. 值处理
2.1 USE_BIG_DECIMAL_FOR_FLOATS
USE_BIG_DECIMAL_FOR_FLOATS(false),
USE_BIG_DECIMAL_FOR_FLOATS
用于配置是否应将 JSON
中的浮点数反序列化为 BigDecimal
对象。默认禁用,因为 Double
类型通常能提供足够的精度,并且性能更好。
2.2 USE_BIG_INTEGER_FOR_INTS
USE_BIG_INTEGER_FOR_INTS(false),
USE_BIG_INTEGER_FOR_INTS
用于配置是否应将 JSON
中的整数(非浮点数)反序列化为 BigInteger
对象。默认禁用,未指定类型的整数默认将使用最紧凑的整数类型进行反序列化,以优化效率。
2.3 USE_LONG_FOR_INTS
USE_LONG_FOR_INTS(false),
USE_LONG_FOR_INTS
用于配置是否应将 JSON
中的整数反序列化为long
类型。默认禁用,将其反序列化为 int
类型(如果值在 int
范围内),或者如果值太大则可能使用 BigInteger
。启用时整数值将被反序列化为 long
对象。
2.4 USE_JAVA_ARRAY_FOR_JSON_ARRAY
USE_JAVA_ARRAY_FOR_JSON_ARRAY(false),
USE_JAVA_ARRAY_FOR_JSON_ARRAY
用于配置在没有明确的类型信息时,是否应将 JSON
数组反序列化为原生 Java
数组(如 int[]
, String[]
等)而不是 List
或其他集合类型。
3. 错误处理
3.1 FAIL_ON_UNKNOWN_PROPERTIES
FAIL_ON_UNKNOWN_PROPERTIES(true),
FAIL_ON_UNKNOWN_PROPERTIES
用于配置在反序列化过程中遇到未知属性(即那些没有对应属性来映射的属性,且没有任何setter
或handler
可以处理这样的属性)时,应该如何处理。
默认启用,如果在JSON
中存在无法映射到目标Java
对象的属性,将抛出一个异常,指示反序列化失败。这样的设计可以帮助开发者及时捕获到数据模型与JSON
结构之间的不匹配,从而进行修复。
例如下方代码中,User
类没有pwd
属性进行反序列化:
String jsonStr="{\"id\":1767798780627279333,\"name\":\"张三\",\"pwd\":null,\"birthday\":1712043815828}";
User user = jsonMapper.readValue(jsonStr, User.class);
默认情况下会报错:
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "pwd" (class com.pearl.jacksoncore.demo.feature.User), not marked as ignorable (10 known properties: "addr", "orgList", "org", "num", "id", "birthday", "age", "aDouble", "roleList", "name"])
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 49] (through reference chain: com.pearl.jacksoncore.demo.feature.User["pwd"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:1153)
禁用該特性,則正常輸出:
String jsonStr="{\"id\":1767798780627279333,\"name\":\"张三\",\"pwd\":null,\"birthday\":1712043815828}";
jsonMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
User user = jsonMapper.readValue(jsonStr, User.class);
3.2 FAIL_ON_NULL_FOR_PRIMITIVES
FAIL_ON_NULL_FOR_PRIMITIVES(false),
FAIL_ON_NULL_FOR_PRIMITIVES
用于配置将 JSON
中的 null
值反序列化为 Java
基本类型(如 int
, boolean
, double
等)时是否抛出异常。
当前有一个用户类,有一个Long
类型,一个long
类型属性:
public class User {
private Long id;
private long userId;
// ..............
}
执行序列化:
User userBy = new User();
userBy.setName("仓大大");
String value = jsonMapper.writeValueAsString(userBy);
System.out.println(value);
Long
输出为null
,long
输出为默认值0
:
{"id":null,"userId":0}
默认关闭,当long
对应的值为null
时,并不会抛出异常,开启后抛出MismatchedInputException
::
String str="{\"id\":null,\"userId\":null}";
jsonMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES,true);
User userByStr = jsonMapper.readValue(str, User.class);
System.out.println(userByStr);
3.3 FAIL_ON_NUMBERS_FOR_ENUMS
FAIL_ON_NUMBERS_FOR_ENUMS(false),
FAIL_ON_NUMBERS_FOR_ENUMS
用于配置JSON
中的数字试图被反序列化为 Java
枚举类型时,是否抛出异常。
3.4 FAIL_ON_INVALID_SUBTYPE
FAIL_ON_INVALID_SUBTYPE(true),
FAIL_ON_INVALID_SUBTYPE
用于配置在反序列化过程中遇到无效的子类型时,是否抛出异常。
3.5 FAIL_ON_READING_DUP_TREE_KEY
FAIL_ON_READING_DUP_TREE_KEY(false),
FAIL_ON_READING_DUP_TREE_KEY
用于配置在解析 JSON
树(Tree Model
)时遇到重复的键时,是否抛出异常。
3.6 FAIL_ON_IGNORED_PROPERTIES
FAIL_ON_IGNORED_PROPERTIES(false),
例如下方代码中,User
类中的id
属性標記了忽略:
public class User {
// 用户ID
@JsonIgnore
private Long id;
//.........
}
默认配置下,反序列化时并不会报错:
// FAIL_ON_IGNORED_PROPERTIES
String strByTest = "{\"id\":123456,\"name\":null}";
User userByTest = jsonMapper.readValue(strByTest, User.class);
System.out.println(userByTest);
开启配置后,JSON
内容存在被忽略的字段,则会报错:
jsonMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, true);
Exception in thread "main" com.fasterxml.jackson.databind.exc.IgnoredPropertyException: Ignored field "id" (class com.pearl.jacksoncore.demo.feature.User) encountered; mapper configured not to allow this (10 known properties: "addr", "orgList", "org", "userId", "name", "birthday", "age", "aDouble", "roleList", "num"])
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 9] (through reference chain: com.pearl.jacksoncore.demo.feature.User["id"])
at com.fasterxml.jackson.databind.exc.IgnoredPropertyException.from(IgnoredPropertyException.java:65)
3.7 FAIL_ON_UNRESOLVED_OBJECT_IDS
FAIL_ON_UNRESOLVED_OBJECT_IDS(true),
FAIL_ON_UNRESOLVED_OBJECT_IDS
用于配置在反序列化过程中遇到无法解析的对象ID
时,是否抛出异常。
在 Jackson
中,可以通过对象 ID
来引用已经序列化过的对象,用来处理循环引用问题。对象 ID
通常是通过 @JsonIdentityInfo
注解来标记的,允许在序列化时给每个对象分配一个唯一的 ID
,并在反序列化时通过这个 ID
来恢复对象引用。
如果在反序列化过程中 Jackson
遇到了一个对象 ID
,但无法找到与之对应的已序列化对象(可能是因为对象没有被正确序列化,或者 ID
引用丢失),默认配置下,会抛出异常。
3.8 FAIL_ON_MISSING_CREATOR_PROPERTIES
FAIL_ON_MISSING_CREATOR_PROPERTIES(false),
FAIL_ON_MISSING_CREATOR_PROPERTIES
则用于在尝试通过创建者创建对象,发现缺少必需的属性时,是否抛出异常。
在反序列化时,对象的创建通常依赖于其构造函数、工厂方法或构建器模式,它们统称为“创建者”(creator
)。创建者可以具有必需的属性(在构造函数中通过参数提供)或可选的属性(通过setter
方法或构建器链式调用设置)。
3.9 FAIL_ON_NULL_CREATOR_PROPERTIES
FAIL_ON_NULL_CREATOR_PROPERTIES(false),
FAIL_ON_NULL_CREATOR_PROPERTIES
在反序列化过程中创建者属性值为 null
时,是否抛出异常。
3.10 FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY
FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY(true),
FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY
用于配置在反序列化多态类型时,如果没有找到表示外部类型 ID
的属性时,是否抛出异常。
3.11 FAIL_ON_TRAILING_TOKENS
FAIL_ON_TRAILING_TOKENS(false),
FAIL_ON_TRAILING_TOKENS
用于配置在解析完一个完整的JSON
对象后遇到额外的令牌时,是否抛出异常。
当 Jackson
解析 JSON
数据时,会按照 JSON
数据的结构顺序逐个读取并处理令牌。令牌可以包括对象的开始和结束标记、数组的开始和结束标记、属性名称、属性值等。在正常情况下,解析器会期望在读取完所有的有效令牌后遇到 JSON
数据的结束(比如文件末尾或输入流的结束)。
然而,在某些情况下,JSON
数据后面可能跟有额外的、不属于该 JSON
对象的令牌。 这可能是因为数据源在 JSON
数据之后包含了其他数据,或者是因为数据在传输过程中被意外地截断了。当遇到额外令牌时,禁用该特征会忽略尾随的令牌并继续执行。启用时,则会排除异常。
3.12 WRAP_EXCEPTIONS
WRAP_EXCEPTIONS(true),
WRAP_EXCEPTIONS
用于配置在遇到异常时是否应该捕获并包装这些异常,包装异常的目的是为了添加关于问题位置的额外信息(例如,在输入数据中的哪个位置出现了问题)。
3.13 FAIL_ON_UNEXPECTED_VIEW_PROPERTIES
FAIL_ON_UNEXPECTED_VIEW_PROPERTIES(false),
FAIL_ON_UNEXPECTED_VIEW_PROPERTIES
用于配置在反序列化过程中,遇到了不属于当前视图的属性时,是否抛出异常。
Jackson
中的视图机制,允许定义哪些属性应该被序列化或反序列化到特定的上下文或用途。通常用于 API
版本控制、数据脱敏、不同客户端的定制数据。通过使用视图,可以控制哪些属性在特定的序列化或反序列化操作中是可用的。
4. 结构转换
4.1 ACCEPT_SINGLE_VALUE_AS_ARRAY
ACCEPT_SINGLE_VALUE_AS_ARRAY(false),
ACCEPT_SINGLE_VALUE_AS_ARRAY
用于配置是否允许单个值反序列化为数组。
正常情况下,List
或者数组类型,序列化后,都是使用[]
表示,也可以使用SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED
配置单个元素时,不用[]
表示。那么将单个反序列化为数组类型时,可以使用ACCEPT_SINGLE_VALUE_AS_ARRAY
支持该场景。
4.2 UNWRAP_SINGLE_VALUE_ARRAYS
UNWRAP_SINGLE_VALUE_ARRAYS(false),
UNWRAP_SINGLE_VALUE_ARRAYS
用于处理 JSON
数组中只包含一个单独值的情况。当启用这个选项时,会在反序列化过程中自动“拆包”只包含一个元素的数组,将其直接映射到目标对象的属性上,而不是将该元素作为数组的一部分。
例如,当前JSON
文本中,name
字段是一个数组,但是在User
类中,name
字段是一个字符串,这时会报错:
String strByUNWRAP_SINGLE_VALUE_ARRAYS = "{\"name\": [\"John\"]}";
开启该特性,单个元素的集合将会被反序列化为单个值:
String strByUNWRAP_SINGLE_VALUE_ARRAYS = "{\"name\": [\"John\"]}";
jsonMapper.configure(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS, true);
User userByByUNWRAP_SINGLE_VALUE_ARRAYS = jsonMapper.readValue(strByUNWRAP_SINGLE_VALUE_ARRAYS, User.class);
System.out.println(userByByUNWRAP_SINGLE_VALUE_ARRAYS);
4.3 UNWRAP_ROOT_VALUE
UNWRAP_ROOT_VALUE(false),
SerializationFeature.WRAP_ROOT_VALUE
在序列化时,最外会加一层根对象包装,开启UNWRAP_ROOT_VALUE
,则可以将对象的根级别属性直接映射到目标Java
对象的属性上,而不是将整个JSON
对象作为一个嵌套的对象来处理。
5. 值转换
5.1 ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
ACCEPT_EMPTY_STRING_AS_NULL_OBJECT(false),
ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
用于配置是否允许将空字符串值(""
)反序列化为null
。 这里只支持属性类型为POJO
、Map
、Collection
对象,如果是String
类型则还是空字符串值。
例如,下方代碼中, name
属性和org
属性都是空字符串:
String strByAAA ="{\"name\":\"\",\"age\":30,\"org\":\"\"}";
反序列化时会报错:
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot coerce empty String ("") to `com.pearl.jacksoncore.demo.pojo.Org` value (but could if coercion was enabled using `CoercionConfig`)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 27] (through reference chain: com.pearl.jacksoncore.demo.feature.User["org"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadCoercion(DeserializationContext.java:1832)
开启该特征则正常输出:
String strByAAA ="{\"name\":\"\",\"age\":30,\"org\":\"\"}";
jsonMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
User userByAAA = jsonMapper.readValue(strByAAA, User.class);
5.2 ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT
ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT(false),
ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT
用于配置是否允许将空数组([]
)反序列化为 null
,和上面的类似。
5.3 ACCEPT_FLOAT_AS_INT
ACCEPT_FLOAT_AS_INT(true),
ACCEPT_FLOAT_AS_INT
用于配置是否允许将浮点类型反序列化为 int
类型 。
示例代码:
String strByAAAA ="{\"name\":\"\",\"age\":30,\"age\":3.14159}";
User userByAAAA = jsonMapper.readValue(strByAAAA, User.class);
System.out.println(userByAAAA);
输出结果:
User{id=null, aDouble=null, name='', age=3, addr='null', org=null, roleList=null}
5.4 READ_ENUMS_USING_TO_STRING
READ_ENUMS_USING_TO_STRING(false),
READ_ENUMS_USING_TO_STRING
用于配置允许在反序列化枚举值的过程中,尝试将字符串与枚举类型中的 toString()
方法法返回的所有值进行匹配,以找到正确的枚举实例。
提供一个示例性别枚举:
public enum GenderEnum {
MAN("man", "男"),
WOMAN("woman", "女");
GenderEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
private String code;
private String desc;
@Override
public String toString() {
return desc;
}
// ............
}
进行序列化,从输出结果可以看出,默认输出的是Enum.name()
方法的返回值:
GenderEnum genderEnum = GenderEnum.MAN;
String strByGenderEnum = jsonMapper.writeValueAsString(genderEnum);
System.out.println(GenderEnum.MAN.name()); // MAN
System.out.println(strByGenderEnum); // "MAN"
在上一篇,有学过可以使用SerializationFeature.WRITE_ENUMS_USING_TO_STRING
调用 toString()
的返回值进行输出:
jsonMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true); // "男"
反序列化时,可以开启READ_ENUMS_USING_TO_STRING
,调用 toString()
方法进行匹配:
jsonMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
String strEnum="\"男\"";
GenderEnum genderEnumByStr = jsonMapper.readValue(strEnum, GenderEnum.class);
System.out.println(genderEnumByStr);
5.5 READ_UNKNOWN_ENUM_VALUES_AS_NULL
READ_UNKNOWN_ENUM_VALUES_AS_NULL(false),
READ_UNKNOWN_ENUM_VALUES_AS_NULL
用于配置在反序列化枚举类型时,如果遇到未知的枚举值,是否作为null
处理。
例如反序列化一个不存在的枚举值:
String strEnumAAA="\"人妖\"";
//jsonMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
GenderEnum strEnumAAAByStr = jsonMapper.readValue(strEnumAAA, GenderEnum.class);
System.out.println(strEnumAAAByStr);
默认配置下,会抛出异常:
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.pearl.jacksoncore.demo.feature.GenderEnum` from String "人妖": not one of the values accepted for Enum class: [女, 男]
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
开启该特征后,反序列化为null
:
null
5.6 READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE
READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE(false),
示例,首先使用@JsonEnumDefaultValue
标识一个默认值:
public enum GenderEnum {
MAN("man", "男"),
WOMAN("woman", "女"),
@JsonEnumDefaultValue
UNKNOWN("unknown", "默认值")
;
// ............
}
开启特性并反序列化一个未知枚举值:
// READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE
String strEnumAAA="\"人妖\"";
jsonMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE, true);
GenderEnum strEnumAAAByStr = jsonMapper.readValue(strEnumAAA, GenderEnum.class);
System.out.println(strEnumAAAByStr); // 默认值
5.7 READ_DATE_TIMESTAMPS_AS_NANOSECONDS
READ_DATE_TIMESTAMPS_AS_NANOSECONDS(true),
READ_DATE_TIMESTAMPS_AS_NANOSECONDS
用于配置将日期和时间戳(Timestamps
)反序列化为纳秒(Nanoseconds
)精度的值。纳秒是时间的最小单位之一,比秒小得多。使用纳秒精度可以捕获更精细的时间变化,这在需要高精度时间记录的场合(如金融交易、科学计算等)非常有用。
5.8 ADJUST_DATES_TO_CONTEXT_TIME_ZONE
ADJUST_DATES_TO_CONTEXT_TIME_ZONE(true),
ADJUST_DATES_TO_CONTEXT_TIME_ZONE
用于配置将日期值反序列化为和当前上下文相关的时区。
6. 其他
6.1 EAGER_DESERIALIZER_FETCH
EAGER_DESERIALIZER_FETCH(true);
EAGER_DESERIALIZER_FETCH
用于配置ObjectReader
是否应该在可能的情况下积极地获取必要的JsonDeserializer
。默认是启用的,除非确实遇到了实际问题,否則没有必要禁用这个特性。