最近有个功能需要对Jackson做很多的个性化配置,在网上找了一圈,大部分只对配置项做了说明,无法直接看到效果。
因此,自己根据源码上的注解,对一些常见的配置做了一下测试。
如有理解错误的地方,欢迎指正、探讨,不喜勿喷,谢谢。
SerializationFeature
用于开启/禁用Java Bean序列化
成JSON有关的特性/功能。
通用输出功能
WRAP_ROOT_VALUE
:将JSON包含在一个根节点下。默认禁用。
INDENT_OUTPUT
:美化输出,缩进格式输出JSON。默认禁用。
错误处理功能
FAIL_ON_EMPTY_BEANS
:序列化空Bean时失败。默认启用。如果禁用,则会将对象序列化为空。一般选择禁用
。
空Bean即
没有任何属性
的Bean,或者有属性但是没有对应的get方法
。
禁用之后,可以正常序列化:
FAIL_ON_SELF_REFERENCES
:自我引用(自身循环引用)时,序列化失败。默认启用。这种场景下如果想正常序列化,可以与 WRITE_SELF_REFERENCES_AS_NULL
结合使用。
WRITE_SELF_REFERENCES_AS_NULL
:自我引用时,序列化为null(即忽略该属性)。默认禁用。启用该功能的前提是禁用 FAIL_ON_SELF_REFERENCES
。
WRAP_EXCEPTIONS
:包装异常,在序列化对象时如果出现异常,会捕获异常,进行包装后再抛出,以提供更详细的错误信息。默认启用。
禁用时的异常信息:
FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS
:序列化时,如果已要求JSON中包含对象的类型信息,但是又有@JsonUnwrapped
注解,则序列化失败。默认启用。
序列化时将类型信息写入JSON,可以用于增强反序列化的安全性,通过指定的白名单,仅允许指定的类型才能反序列化成功。
如下所示,由于没有配置org.example.
白名单,反序列化失败了:
在类上使用@JsonTypeInfo
注解,也可以在序列化的JSON中包含对象的类型信息。
@JsonUnwrapped
注解可以让对象平铺(去掉了JSON中的层级关系)。
当序列化时要求带上类型,但是又有@JsonUnwrapped
注解时,默认会序列化失败,因为无法序列化Person
的类型信息。
@JsonTypeInfo
也一样有问题
将FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS
设置为禁用,即可序列化成功,但是不会序列化对应的类型信息。
控制被序列化对象的生命周期
CLOSE_CLOSEABLE
:对象实现了Closeable
接口,序列化后自动调用close()
方法。默认禁用(不调用close()
方法)。
例如MyBatis分页查询插件PageHelper中的Page对象。
FLUSH_AFTER_WRITE_VALUE
:ObjectMapper
有一组重载的writeValue()
方法,如下图所示。看源码的注释,好像是当调用下图中标记的writeVlaue()
方法完成之后,调用参数JsonGenerator
对象的flush()
方法。默认启用。
特定数据类型的配置
日期类型
WRITE_DATES_AS_TIMESTAMPS
:日期类型序列化成时间戳。默认启用。如果禁用默认使用StdDateFormat(yyyy-MM-dd'T'HH:mm:ss.SSSX)
格式化日期。
如果日期是
Map
的key
,则不受此功能的影响,应该使用WRITE_DATE_KEYS_AS_TIMESTAMPS
进行控制。
可以设置全局的
DateFormat
或者在属性上使用@JsonFormat
指定想要的格式。如果是JDK8
中的日期类型,设置全局的DateFormat
无用,需要注册对应的序列化和反序列化器。
WRITE_DATE_KEYS_AS_TIMESTAMPS
:Map
日期类型的key
序列化为时间戳。默认禁用,使用StdDateFormat(yyyy-MM-dd'T'HH:mm:ss.SSSX)
格式化日期。
设置全局的日期格式,对Map日期类型的key同样生效。
WRITE_DATES_WITH_ZONE_ID
:序列化日期上的时区ID
。默认禁用。启用时,日期的后面会带上时区ID,这种日期反序列化可能会有问题。
WRITE_DATES_WITH_CONTEXT_TIME_ZONE
:使用ObjectMapper
上下文中的时区
序列化日期,对没有时区信息的日期类型无效。默认启用。禁用则使用默认的时区进行序列化日期。
WRITE_DURATIONS_AS_TIMESTAMPS
:Duration
类型的对象序列化为时间戳。默认启用。
WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS
:将日期类型序列化为时间戳时,是否带纳秒
。启用:带纳秒,禁用:不带纳秒。默认启用。
只对JDK8中的日期类型有效,对旧的Date无效。
注意:此功能与反序列化READ_DATE_TIMESTAMPS_AS_NANOSECONDS
的功能对应。
枚举
WRITE_ENUMS_USING_TO_STRING
:枚举值的序列化方式。启用时,使用Enum.toString()
的返回值;禁用时,使用Enum.name()
的返回值。默认禁用。
如果没有重写
Enum.toString()
方法,则Enum.toString()
方法的返回值与Enum.name()
相同。
注意:此功能通常与反序列化READ_ENUMS_USING_TO_STRING
功能的值相同。
WRITE_ENUMS_USING_INDEX
:枚举值的序列化方式。启用时,枚举序列化为数字
(序号,从0开始),使用Enum.ordinal()
的返回值。禁用时,枚举序列化为文本
。默认禁用。
注意:此功能的优先级高于
WRITE_ENUMS_USING_TO_STRING
,只有将此功能设置为false
时才会考虑WRITE_ENUMS_USING_TO_STRING
。
注意:枚举作为Map
的key
时,不受此功能的影响,应该使用WRITE_ENUM_KEYS_USING_INDEX
。
WRITE_ENUM_KEYS_USING_INDEX
:枚举值的序列化方式。枚举作为Map
的key
时,序列化为数字
(序号)。默认禁用。
注意:此功能的优先级低于
WRITE_ENUMS_USING_TO_STRING
。
数组、集合、Map
WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS
:char数组
的序列化方式。启用时,将char数组
序列化为数组,元素是单字符的字符串。禁用时,将char数组
序列化为字符串。默认禁用。
WRITE_NULL_MAP_VALUES
:Map
中null值
的序列化方式。启用时,序列化null值
;禁用时,不序列化null值
。默认启用。
从2.9版本开始废弃,建议使用
JsonInclude.Include.NON_NULL
过滤null。
WRITE_EMPTY_JSON_ARRAYS
:空集合
、空数组
的序列化方式。启用时,序列化为空数组;禁用时,不序列化。默认启用。对Map
无效。
从2.8版本开始废弃,建议使用
JsonInclude.Include.NON_EMPTY
过滤空集合、空数组。
WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED
:只有单个元素的集合、数组
的序列化方式。启用时,正常序列化为数组;禁用时,不序列化为数组(去掉了层级)。默认禁用。
注意:此功能与反序列化
ACCEPT_SINGLE_VALUE_AS_ARRAY
的功能对应。
ORDER_MAP_ENTRIES_BY_KEYS
:序列化Map
时按Key进行排序
。启用:排序;禁用:不排序。默认禁用。
其他类型
WRITE_BIGDECIMAL_AS_PLAIN
:BigDecimal
的序列化方式。启用时,使用BigDecimal.toPlainString()
的返回值;禁用时,使用BigDecimal.toString()
的返回值,可能出现科学计数法
。默认禁用。
从2.5版本开始废弃,建议使用
JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN
。
BigDecimal
有三个toString()
方法:
toEngineeringString
:有必要时使用工程计数法。工程记数法与科学技术法类似,但要求10的幂必须是3的倍数;
toPlainString
:不使用任何指数;
toString
:有必要时使用科学计数法。