Jackson 2.x 系列【14】特征配置篇之 MapperFeature

有道无术,术尚可求,有术无道,止于术。

本系列Jackson 版本 2.17.0

源码地址:https://gitee.com/pearl-organization/study-jaskson-demo

1. 前言

在前两篇文档中,我们介绍了jackson-databind模块提供的SerializationFeatureDeserializationFeature特征枚举类,它们主要作用于值的处理,比如数据类型转换、错误处理等,而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字段,其gettersetter方法仍然存在,那么这些方法仍然可以被用于序列化和反序列化过程中。 开启时,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修饰,但是有getteris方法

Jackson在反序列化时,默认只会作用于以下属性:

  • public修饰,可没有setter方法
  • public修饰,但是有setter方法

该特征默认开启,Jackson会自动检测属性。禁用时,则只有明确带有注解(@JsonProperty@JsonAutoDetect)的字段才会被视作属性。

3.3 AUTO_DETECT_GETTERS

    AUTO_DETECT_GETTERS(true),

AUTO_DETECT_GETTERS用于配置是否将无参的get开头的方法视为属性。

JSON数据的属性与Java对象的字段名不匹配时,Jackson会查找是否存在匹配的gettersetter方法来辅助映射。

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}来访问原本不可访问的对象。

默认开启,即使类的字段或方法的访问修饰符(如 privateprotected)限制了它们的可见性,也能够访问和修改这些字段或方法。覆盖访问修饰符允许从类的外部访问和修改原本应该被隐藏的内部状态,这违反了Java的封装原则,可能会导致代码的安全性、可维护性和健壮性。

开启时,Jackson会通过反射调用AccessibleObject#setAccessible,临时设置 FieldMethodConstructor 对象的可访问性,这样能够访问之前因为访问权限问题而无法访问的字段、方法或构造器。

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的属性可以接收myPropertyMyPropertyMYPROPERTY等任何大小写组合的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会根据这个特性决定是否使用类中定义的默认值来填充这个字段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨 禹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值