有道无术,术尚可求,有术无道,止于术。
本系列Jackson 版本 2.17.0
源码地址:https://gitee.com/pearl-organization/study-jaskson-demo
文章目录
- 1. 前言
- 2. 通用
- 2.1 USE_ANNOTATIONS
- 2.2 USE_GETTERS_AS_SETTERS
- 2.3 PROPAGATE_TRANSIENT_MARKER
- 3. 自动检测
- 3.1 AUTO_DETECT_CREATORS
- 3.2 AUTO_DETECT_FIELDS
- 3.3 AUTO_DETECT_GETTERS
- 3.4 AUTO_DETECT_IS_GETTERS
- 3.5 AUTO_DETECT_SETTERS
- 3.6 REQUIRE_SETTERS_FOR_GETTERS
- 3.7 ALLOW_FINAL_FIELDS_AS_MUTATORS
- 3.8 INFER_PROPERTY_MUTATORS
- 3.9 INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
- 3.10 ALLOW_VOID_VALUED_PROPERTIES
- 4. 访问修饰符处理
- 4.1 CAN_OVERRIDE_ACCESS_MODIFIERS
- 4.2 OVERRIDE_PUBLIC_ACCESS_MODIFIERS
- 5. 类型处理
- 5.1 USE_STATIC_TYPING
- 5.2 USE_BASE_TYPE_AS_DEFAULT_IMPL
- 5.3 INFER_BUILDER_TYPE_BINDINGS
- 5.4 REQUIRE_TYPE_ID_FOR_SUBTYPES
- 6. 视图
- 6.1 DEFAULT_VIEW_INCLUSION
- 7. 输出
- 7.1 SORT_PROPERTIES_ALPHABETICALLY
- 7.2 SORT_CREATOR_PROPERTIES_FIRST
- 8. 名称相关
- 8.1 ACCEPT_CASE_INSENSITIVE_PROPERTIES
- 8.2 ACCEPT_CASE_INSENSITIVE_ENUMS
- 8.3 ACCEPT_CASE_INSENSITIVE_VALUES
- 8.4 USE_WRAPPER_NAME_AS_PROPERTY_NAME
- 8.5 USE_STD_BEAN_NAMING
- 8.6 ALLOW_EXPLICIT_PROPERTY_RENAMING
- 8.7 ALLOW_IS_GETTERS_FOR_NON_BOOLEAN
- 9. 强制转换
- 9.1 ALLOW_COERCION_OF_SCALARS
- 10. 其他
- 10.1 IGNORE_DUPLICATE_MODULE_REGISTRATIONS
- 10.2 IGNORE_MERGE_FOR_UNMERGEABLE
- 10.3 BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES
- 10.4 APPLY_DEFAULT_VALUES
1. 前言
在前两篇文档中,我们介绍了jackson-databind
模块提供的SerializationFeature
、DeserializationFeature
特征枚举类,它们主要作用于值的处理,比如数据类型转换、错误处理等,而MapperFeature
则用于映射处理,即Java Bean
属性和Json
属性之前的映射。
接下来我们了解MapperFeature
中的所有特征,到此,特征配置篇就结束了,
2. 通用
2.1 USE_ANNOTATIONS
USE_ANNOTATIONS(true),
USE_ANNOTATIONS
用于配置是否使用注解来来配置ObjectMapper
的行为。默认开启,ObjectMapper
会使用配置的AnnotationIntrospector
来读取和处理Java
类上的注解。
示例当前User
类有一个忽略注解:
默认进行序列化时,id
字段会被忽略,如果禁用USE_ANNOTATIONS
,这些类上的注解都不会生效:
JsonMapper jsonMapper = JsonMapper.builder()
.disable(MapperFeature.USE_ANNOTATIONS)
.build();
// USE_ANNOTATIONS
User user = new User();
user.setId(1767798780627279333L);
user.setName("测试");
user.setBirthday(new Date());
String jsonStrAA = jsonMapper.writeValueAsString(user);
System.out.println(jsonStrAA);
2.2 USE_GETTERS_AS_SETTERS
USE_GETTERS_AS_SETTERS(true),
USE_GETTERS_AS_SETTERS
用于配置是否允许使用getter
方法来修改集合(Collections
)和映射(Maps
)类型的属性,而不需要相应的setter
方法。
2.3 PROPAGATE_TRANSIENT_MARKER
PROPAGATE_TRANSIENT_MARKER(false),
PROPAGATE_TRANSIENT_MARKER
用于配置如何处理被transient
修饰的字段。
默认禁用,如果有一个transient
字段,其getter
和setter
方法仍然存在,那么这些方法仍然可以被用于序列化和反序列化过程中。 开启时,transient
字段将会被忽略。
3. 自动检测
3.1 AUTO_DETECT_CREATORS
AUTO_DETECT_CREATORS(true),
AUTO_DETECT_CREATORS
用于配置是否应该自动检测并启用类的构造器(包括默认构造器、带参数的构造器以及工厂方法)以用于反序列化。
默认启用,反序列化时会查找默认构造器、带参数的构造器以及工厂方法(@JsonCreator
注解指定)来创建对象实例。禁用时,必须使用 @Jsoncreator
注解去指定一个方法用于创建对象(无参构造除外)。
3.2 AUTO_DETECT_FIELDS
AUTO_DETECT_FIELDS(true),
AUTO_DETECT_FIELDS
用于配置是否开启自动检测非静态字段为属性。
Jackson
在序列化时,除了默认只会作用于以下属性:
public
修饰,可没有getter
方法- 非
public
修饰,但是有getter
或is
方法
Jackson
在反序列化时,默认只会作用于以下属性:
public
修饰,可没有setter
方法- 非
public
修饰,但是有setter
方法
该特征默认开启,Jackson
会自动检测属性。禁用时,则只有明确带有注解(@JsonProperty
、@JsonAutoDetect
)的字段才会被视作属性。
3.3 AUTO_DETECT_GETTERS
AUTO_DETECT_GETTERS(true),
AUTO_DETECT_GETTERS
用于配置是否将无参的get
开头的方法视为属性。
当JSON
数据的属性与Java
对象的字段名不匹配时,Jackson
会查找是否存在匹配的getter
和setter
方法来辅助映射。
3.4 AUTO_DETECT_IS_GETTERS
AUTO_DETECT_IS_GETTERS(true),
AUTO_DETECT_IS_GETTERS
用于配置是否将无参的is
开头,并且返回值是boolean
类型的方法视为属性。
3.5 AUTO_DETECT_SETTERS
AUTO_DETECT_SETTERS(true),
AUTO_DETECT_SETTERS
用于配置是否将无参的set
开头的方法视为属性。
REQUIRE_SETTERS_FOR_GETTERS
用于配置在没有匹配的setter
方法、构造器参数或字段时,是否动检测getter
方法。
3.6 REQUIRE_SETTERS_FOR_GETTERS
REQUIRE_SETTERS_FOR_GETTERS(false),
3.7 ALLOW_FINAL_FIELDS_AS_MUTATORS
ALLOW_FINAL_FIELDS_AS_MUTATORS(true),
ALLOW_FINAL_FIELDS_AS_MUTATORS
用于配置允许在反序列化过程中尝试将JSON
数据中的值赋给对象的 final
字段。
由于Java
的语言规则,final
字段的值只能在声明时或构造过程中被赋值,之后不能再被修改。因此,这个特性实际上允许在对象的构造过程中使用这些 final
字段。
3.8 INFER_PROPERTY_MUTATORS
INFER_PROPERTY_MUTATORS(true),
INFER_PROPERTY_MUTATORS
用于配置是否使用getter
方法推断出对象的属性值,即使属性和setter
设置为私有,或者不存在setter
方法。
例如有一个标准的POJO
:
public class MutatorsVO {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("setName");
this.name = name;
}
public MutatorsVO() {
System.out.println("无参构造");
}
@Override
public String toString() {
return "MutatorsVO{" +
"name='" + name + '\'' +
'}';
}
}
执行反序列化:
String strByMutatorsVO="{\"name\":\"张三\"}";
MutatorsVO mutatorsVOByStr = jsonMapper.readValue(strByMutatorsVO, MutatorsVO.class);
System.out.println(mutatorsVOByStr);
从输出结果中可以看出,反序列化时,使用默认的构造方法创建对象,使用setter
方法设置属性:
无参构造
setName
MutatorsVO{name='张三'}
当我们注释掉setter
方法时,依然能够正确的反序列化,这是因为默认开启了INFER_PROPERTY_MUTATORS
,使用getName
方法推断出对象的name
属性值,如果禁用该特征,则会报错:
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "name" (class com.pearl.jacksoncore.demo.feature.MutatorsVO), not marked as ignorable (0 known properties: ])
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 10] (through reference chain: com.pearl.jacksoncore.demo.feature.MutatorsVO["name"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
3.9 INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES(true),
INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
用于配置如何处理JavaEE中的@ConstructorProperties
注解。 默认启用,@ConstructorProperties
和@JsonCreator
效果相同。
3.10 ALLOW_VOID_VALUED_PROPERTIES
ALLOW_VOID_VALUED_PROPERTIES(false),
ALLOW_VOID_VALUED_PROPERTIES
用于配置允许通过Getter
方法返回Void
类型来表示一个值为null
的伪属性。
例如下方POJO
类,实际只存在一个name
属性:
public class VoidVO {
public String name;
public String getPseudoProperty() {
return "伪属性";
}
}
Jackson
默认情况下会序列化public
修饰、get
方法开头的属性,例如上面getPseudoProperty
方法,会输出一个seudoProperty
属性(实际POJO
类不存在该属性):
{"name":null,"pseudoProperty":"伪属性"}
开启ALLOW_VOID_VALUED_PROPERTIES
,则表示允许Getter
方法返回类型Void
,最终会被序列化为null
:
public Void getPseudoProperty() {
return null;
}
4. 访问修饰符处理
4.1 CAN_OVERRIDE_ACCESS_MODIFIERS
CAN_OVERRIDE_ACCESS_MODIFIERS(true),
CAN_OVERRIDE_ACCESS_MODIFIERS
用于配置在反序列化过程中是否可以覆盖Java
类的访问修饰符,通过调用方法{@link java.lang.reflect.AccessibleObject#setAccessible}
来访问原本不可访问的对象。
默认开启,即使类的字段或方法的访问修饰符(如 private
或 protected
)限制了它们的可见性,也能够访问和修改这些字段或方法。覆盖访问修饰符允许从类的外部访问和修改原本应该被隐藏的内部状态,这违反了Java
的封装原则,可能会导致代码的安全性、可维护性和健壮性。
开启时,Jackson
会通过反射调用AccessibleObject#setAccessible
,临时设置 Field
、Method
或 Constructor
对象的可访问性,这样能够访问之前因为访问权限问题而无法访问的字段、方法或构造器。
4.2 OVERRIDE_PUBLIC_ACCESS_MODIFIERS
OVERRIDE_PUBLIC_ACCESS_MODIFIERS(true),
OVERRIDE_PUBLIC_ACCESS_MODIFIERS
用于配置是否允许在反序列化过程中是否可以覆盖Java
类的public
访问修饰符。默认开启,从而不需要每次反射时进行访问检查,可以提升性能。
5. 类型处理
5.1 USE_STATIC_TYPING
USE_STATIC_TYPING(false),
USE_STATIC_TYPING
用于配置序列化时是否应该使用实际动态的运行时类型,还是声明的静态类型。反序列化总是使用声明的静态类型,因为在使用类型信息创建实例时,运行时类型是不可用的。
5.2 USE_BASE_TYPE_AS_DEFAULT_IMPL
USE_BASE_TYPE_AS_DEFAULT_IMPL(false),
USE_BASE_TYPE_AS_DEFAULT_IMPL
用于配置如果没有通过@JsonTypeInfo.defaultImpl
注解显式指定默认类,是否应使用多态值的声明基类型作为“默认”实现。
注意:此特性仅对常规多态属性的反序列化有影响,不会影响非多态情况
5.3 INFER_BUILDER_TYPE_BINDINGS
INFER_BUILDER_TYPE_BINDINGS(true),
INFER_BUILDER_TYPE_BINDINGS
用于配置是否允许在反序列化过程中从值类型推断出构建器的类型绑定,在使用带有泛型参数的构建器模式时特别有用。
5.4 REQUIRE_TYPE_ID_FOR_SUBTYPES
REQUIRE_TYPE_ID_FOR_SUBTYPES(true),
在多态反序列化中,一个基类或接口可能有多个子类型,而JSON
数据需要被映射到这些子类型之一。有时候JSON
数据中可能不包含足够的信息来明确指定应该使用哪个子类型, REQUIRE_TYPE_ID_FOR_SUBTYPES
特性允许开发者控制在这种情况下的行为方式。
默认启用,在缺少类型信息的情况下,会抛出一个{@code InvalidTypeIdException}
异常。禁用此特性,那么缺少类型信息的情况下,如果子类型是一个合法的目标(非抽象类),反序列化过程可能会继续进行。
6. 视图
6.1 DEFAULT_VIEW_INCLUSION
DEFAULT_VIEW_INCLUSION(true),
DEFAULT_VIEW_INCLUSION
用于配置没有@JsonView
标识的属性,是否包含在JSON
序列化视图中。
7. 输出
7.1 SORT_PROPERTIES_ALPHABETICALLY
SORT_PROPERTIES_ALPHABETICALLY(false),
SORT_PROPERTIES_ALPHABETICALLY
用于配置POJO
对象属性的序列化顺序。默认禁用,表示不定义顺序,基于JDK
提供的顺序,可能是声明顺序,但不保证。启用时,默认的排序方式是字母顺序。
注意:不适用于 {@link java.util.Map}
序列化
7.2 SORT_CREATOR_PROPERTIES_FIRST
SORT_CREATOR_PROPERTIES_FIRST(true),
SORT_CREATOR_PROPERTIES_FIRST
用于配置在需要使用字母顺序对属性进行排序时,是否应将创建者属性(通过构造函数或静态工厂方法传递的属性)排序在其他没有指定显式顺序的属性之前。
注意:在任何情况下,显式顺序都将优先于这个设置。禁用此特性可能会对反序列化性能产生负面影响,输入中所有位于最后一个创建者属性之前的属性都需要被缓冲,因为所有创建者属性都是创建实例所必需的。启用此特性可以确保尽可能减少缓冲。
8. 名称相关
8.1 ACCEPT_CASE_INSENSITIVE_PROPERTIES
ACCEPT_CASE_INSENSITIVE_PROPERTIES(false),
ACCEPT_CASE_INSENSITIVE_PROPERTIES
用于配置是否允许对传入的JSON
进行更宽松的反序列化。
当该特性被启用时,JavaBean
的属性将与它们的小写等价项进行匹配,无论传入的JSON
中属性的大小写组合如何,只要它们的小写形式与JavaBean
的属性名匹配,就可以成功地进行反序列化。例如,JavaBean
中名为myProperty
的属性可以接收myProperty
、MyProperty
、MYPROPERTY
等任何大小写组合的JSON
属性。
启用这个特性会带来一些额外的性能开销,因为对于包含大写字母的属性名,需要在比较之前将其转换为小写。为了保持Jackson
的默认行为和向后兼容性,这个特性默认是禁用的。
8.2 ACCEPT_CASE_INSENSITIVE_ENUMS
ACCEPT_CASE_INSENSITIVE_ENUMS(false),
ACCEPT_CASE_INSENSITIVE_ENUMS
用于配置在反序列化枚举(Enum
)时是否应该区分大小写。
如果启用了该特性,枚举的反序列化将忽略大小写。这意味着传入的字符串值(作为待反序列化的数据)与枚举标识符(可能是通过name()
方法、toString()
方法或显式覆盖获得的)之间的大小写不需要匹配。该特性应该同时适用于将枚举作为值进行反序列化和将枚举作为Map
的键进行反序列化。
8.3 ACCEPT_CASE_INSENSITIVE_VALUES
ACCEPT_CASE_INSENSITIVE_VALUES(false),
ACCEPT_CASE_INSENSITIVE_VALUES
用于配置是否允许在反序列化时解析一些基于文本的枚举值类型,同时忽略这些值的大小写。
无论传入的JSON
中的枚举值是大写、小写还是混合大小写,只要它们与期望的枚举值在忽略大小写的情况下匹配,就可以被正确解析。这个特性主要用于处理那些文本表示形式可能因大小写差异而有所不同的枚举类型,例如,日期/时间类型的反序列化器就可以利用这个特性来解析不同大小写的日期/时间字符串。
注意:该特性是否支持取决于具体的反序列化器实现是否使用了它。并不是所有的基于文本的枚举值类型反序列化器都会自动忽略大小写。常规的Enum
类型并不遵循这个特性,而是遵循ACCEPT_CASE_INSENSITIVE_ENUMS
。
8.4 USE_WRAPPER_NAME_AS_PROPERTY_NAME
USE_WRAPPER_NAME_AS_PROPERTY_NAME(false),
USE_WRAPPER_NAME_AS_PROPERTY_NAME
用于配置是否允许属性名被包装器名称(wrapper name
)覆盖。通常,这个包装器名称是通过注解检测到的,如AnnotationIntrospector#findWrapperName
所定义的那样。
当该特性被启用时,所有具有关联的非空包装器名称的属性将使用这个包装器名称,而不是原来的属性名。这允许你在序列化或反序列化JSON
时,以不同的名称来表示属性。
8.5 USE_STD_BEAN_NAMING
USE_STD_BEAN_NAMING(false),
USE_STD_BEAN_NAMING
用于配置是否强制Jackson
与标准的Bean
名称内省(introspection
)保持严格的兼容性,而不是使用默认的稍有差异的机制。
Jackson
在将Java Bean
的方法转换为JSON
属性名时,默认会将方法名中的首字母大写转换为小写,例如getURL()
方法会被转换为url
属性。而标准的Bean
命名规则则仅在首字母大写且后面没有紧跟着另一个大写字母的情况下,才将首字母转换为小写。因此,按照标准的Bean
命名规则,getURL()
方法应该被转换为URL
属性。
启用该特性后,Jackson
会遵循标准的Bean
命名规则,而不是它自己的默认规则。这有助于确保Jackson
在处理Java Bean
时与其他遵循标准Bean
命名规则的库或工具保持一致性。
为了保持向后兼容性,该特性默认是禁用的。早期的Jackson
版本使用的是自己的命名机制。如果你需要确保Jackson
与标准的Bean
命名规则严格兼容,可以显式地启用这个特性。
8.6 ALLOW_EXPLICIT_PROPERTY_RENAMING
ALLOW_EXPLICIT_PROPERTY_RENAMING(false),
ALLOW_EXPLICIT_PROPERTY_RENAMING
用于配置是否允许使用@JsonProperty
注解显式命名的属性(即字段或方法)可以被配置的PropertyNamingStrategy
重新命名。
在Java
类的字段或方法上使用@JsonProperty
注解并指定一个明确的名称时,在序列化和反序列化JSON
时会使用这个名称来映射Java
对象的属性与JSON
中的字段。默认情况下,即使你配置了PropertyNamingStrategy
(用于自定义属性命名策略),Jackson
也不会改变使用@JsonProperty
注解显式指定的名称。
如果启用了该特性,即使字段或方法上使用了@JsonProperty
注解,PropertyNamingStrategy
也可以重新命名这些属性。
8.7 ALLOW_IS_GETTERS_FOR_NON_BOOLEAN
ALLOW_IS_GETTERS_FOR_NON_BOOLEAN(false),
ALLOW_IS_GETTERS_FOR_NON_BOOLEAN
用于配置是否允许is-
前缀的getter
方法用于非布尔型返回类型。
该特性会影响到Java
对象的属性与JSON
中的字段之间的映射关系。默认情况下,Jackson
期望以is-
前缀命名的方法返回布尔类型,并将这些方法作为getter
方法,用于获取Java
对象的布尔属性。
默认禁用,主要是为了保持向后兼容性。启用时,即使方法的返回类型不是布尔型,Jackson
也会将其视为getter
方法,并将其与JSON
中的字段进行映射。
9. 强制转换
9.1 ALLOW_COERCION_OF_SCALARS
ALLOW_COERCION_OF_SCALARS(true),
ALLOW_COERCION_OF_SCALARS
用于配置是否允许对简单的非文本标量类型(如数字和布尔值)进行从次要表示形式的强制转换。包括primitive
类型及其包装类,但不包括java.lang.String
和日期/时间类型。
默认启用,允许从JSON
字符串进行转换,只要文本值匹配,例如,字符串"true"
可以作为JSON
布尔值true
的等效值,字符串"1.0"
可以作为double
类型的值。禁用时,仅允许绑定严格兼容的输入,即数字对应数字,布尔值对应布尔值。
10. 其他
10.1 IGNORE_DUPLICATE_MODULE_REGISTRATIONS
IGNORE_DUPLICATE_MODULE_REGISTRATIONS(true),
IGNORE_DUPLICATE_MODULE_REGISTRATIONS
用于配置当相同模块被多次注册时,是否应该忽略这些重复注册。
10.2 IGNORE_MERGE_FOR_UNMERGEABLE
IGNORE_MERGE_FOR_UNMERGEABLE(true),
IGNORE_MERGE_FOR_UNMERGEABLE
用于配置在合并不支持合并的属性时,操作是被忽略还是抛出异常。默认开启,对于不支持合并的属性值,合并操作将被忽略,并且会使用新的值来创建属性。禁用时,将会抛出一个异常。
10.3 BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES
BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES(false),
BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES
用于配置ObjectMapper.enableDefaultTyping()
方法使用默认的PolymorphicTypeValidator
作为基于注解的多态处理的默认验证器。通过启用这个设置,可以阻止使用一组“不安全”的基类型(如 java.lang.Object
),这些基类型是通过那些不要求显式传递PolymorphicTypeValidator
的方法使用的。
建议启用这个设置,因为它可以帮助提高JSON
处理的安全性。在2.x
版本中,出于向后兼容性的原因,这个功能默认是禁用的。但在3.0
版本中,它将成为默认设置,并且该特性可能会被移除。
10.4 APPLY_DEFAULT_VALUES
APPLY_DEFAULT_VALUES(true);
APPLY_DEFAULT_VALUES
用于配置ObjectReader
在输入数据省略了相关值时,是否应用类定义中定义的默认值。
默认启用,当处理JSON
或其他形式的输入数据时,如果数据中没有包含某个字段的值,ObjectReader
会根据这个特性决定是否使用类中定义的默认值来填充这个字段。