掘金 后端 ( ) • 2024-05-05 17:13

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

本系列 Jackson 版本 2.17.0

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

1. 前言

本篇介绍JsonFactoryJsonGeneratorJsonParser提供的内部枚举类,因为它们是底层API,所以其特征也偏底层处理,实际开发中很少去修改默认配置,对于我们来说,也是了解即可。

2. 特征说明

2.1 JsonFactory.Feature

在之前,我们了解过JsonFactory工厂类用于创建JsonGeneratorJsonParser对象,JsonFactory.Feature的特性则同时影响这两个对象。

可以看到JsonFactory.Feature只有几个特征,默认都是开启的,我们在实际开发中,无需也最好不要修改默认配置。这些特征并不是很好使用代码演示,对于开发者来说了解即可。

    public static enum Feature implements JacksonFeature {
    	// 是否调用`String#intern`(字符串常量池机制)获取`JSON`对象属性名称,开启了CANONICALIZE_FIELD_NAMEES才有效
        INTERN_FIELD_NAMES(true),
        // `JSON`对象的属性名是否需要进行规范化
        CANONICALIZE_FIELD_NAMES(true),
        // 符号处理过程中遇到哈希碰撞数量超过安全阈值时,是否会抛出一个IllegalStateException异常
        FAIL_ON_SYMBOL_HASH_OVERFLOW(true),
        // 是否使用RecyclerPool来分配和可能回收BufferRecycler。RecyclerPool的默认实现使用了ThreadLocal和SoftReference来高效地重用底层的输入/输出缓冲区
        USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING(true),
        // 控制基于字节的输入(如byte[]数组或InputStream流)的字符集检测,允许你控制JSON解析器如何处理不同编码的字节输入
        CHARSET_DETECTION(true);
}

2.2 JsonGenerator.Feature

JsonGenerator.Feature是生成器的特征枚举类,下图中可以看到很多特性标记为了过时,推荐使用JsonWriteFeature,所以这里只讲解没有过时的一些特征。

        AUTO_CLOSE_TARGET(true),

AUTO_CLOSE_TARGET自动关闭目标枚举,默认开启,用于配置是否会自动关闭那些不由生成器(JsonGenerator)自身所拥有的底层输出目标。开启状态下,JsonGenerator关闭(调用close方法)时,会自动关闭底层的输出流。可以简化资源管理,减少因忘记关闭资源而导致的潜在问题。

        AUTO_CLOSE_JSON_CONTENT(true),

AUTO_CLOSE_JSON_CONTENT自动关闭JSON内容枚举,默认开启,当在写入JSON内容时忘记了writeEndObject、writeEndArray时,可以自动添加结束标识,可以减少因未正确关闭数组或对象而导致的错误和无效JSON的风险。

        FLUSH_PASSED_TO_STREAM(true),

FLUSH_PASSED_TO_STREAM默认开始,当调用生成器的flush方法时,将会自动触发对底层OutputStreamWriterflush()方法,可以确保所有挂起的数据都被刷新到底层的数据流或文件。

        WRITE_BIGDECIMAL_AS_PLAIN(false),

WRITE_BIGDECIMAL_AS_PLAIN默认关闭,用于配置如何序列化java.math.BigDecimal类型。关闭时BigDecimal的序列化将使用默认的输出模式,BigDecimal对象可能会使用toString()方法,这可能会返回科学记数法表示的值。开启时BigDecimal的值总是以普通的十进制数形式输出。

        STRICT_DUPLICATE_DETECTION(false),

STRICT_DUPLICATE_DETECTION默认关闭,配置是否会主动检查在生成的JSON对象中是否有重复的字段名。开启时JsonGenerator将在生成JSON时检查当前上下文中的所有字段名,并在发现重复的字段名时抛出JsonGenerationException异常。

        IGNORE_UNKNOWN(false),

IGNORE_UNKNOWN默认关闭,启动时尝试写入一个未定义的属性时,这个属性会被静默地忽略,即不会抛出异常,也不会在输出中显示。禁用时写入未知属性时,将会抛出一个JsonProcessingException异常。对于JSON格式,这个特性没有作用,因为JSON不需要预先定义属性。

        ESCAPE_FORWARD_SLASHES(false);

ESCAPE_FORWARD_SLASHES默认关闭,指定JsonGenerator是否应转义正斜杠,Jackson 2.x版本默认禁用该功能,Jackson 3.0默认启用。

2.3 JsonParser.Feature

JsonParser.Feature是生成器的特征枚举类,下图中可以看到很多特性标记为了过时,推荐使用JsonReadFeature,所以这里只讲解没有过时的一些特征。

        AUTO_CLOSE_SOURCE(true),

AUTO_CLOSE_SOURCE默认开始,控制JsonParser在遇到不属于它自身所有的底层输入源时,是否会自动关闭这个输入源。默认情况下,当JsonParser关闭时,会自动关闭用于创建JsonParser的底层InputStreamReader实例。

        ALLOW_COMMENTS(false),

ALLOW_COMMENTS默认关闭,配置JsonParser是否允许解析Java/C++风格注释的特性。由于JSON规范不支持注释,这个特性是非标准的,且默认是禁用的。从Jackson 2.10开始,推荐使用JsonReadFeature#ALLOW_JAVA_COMMENTS来配置这个特性。

        ALLOW_YAML_COMMENTS(false),

ALLOW_YAML_COMMENTS默认关闭,配置JsonParser是否允许解析YAML风格的注释。 由于JSON规范不支持注释,这个特性是非标准的,且默认是禁用的。推荐使用JsonReadFeature#ALLOW_YAML_COMMENTS来配置这个特性。

         STRICT_DUPLICATE_DETECTION(false),

STRICT_DUPLICATE_DETECTION默认关闭,配置JsonParser是否应该检查JSON对象中的重复字段名。启用该特性会增加性能开销,增加基础解析的执行时间约20-30%JsonParser会检查当前上下文中的所有字段名,并在遇到重复字段名时抛出一个JsonParseException异常。

         IGNORE_UNDEFINED(false),

IGNORE_UNDEFINED默认关闭,该特性决定了当底层数据格式需要知道所有属性才能解码(通常通过模式Schema),并且如果输入内容包含的属性在定义中找不到时,应该如何处理。这个特性默认是禁用的,如果底层数据格式需要知道所有属性才能输出,而尝试读取一个未知的属性时,将会抛出一个JsonProcessingException异常。

         INCLUDE_SOURCE_IN_LOCATION(false),

INCLUDE_SOURCE_IN_LOCATION默认关闭,该特性决定了JsonLocation实例是否应该包含对源数据的引用。可用于控制在解析异常等情况下是否泄露有关源数据的详细信息。出于安全考虑,从2.16版本开始,这个特性默认是禁用的。开发者可以根据需要和安全要求来决定是否启用这个特性。

         USE_FAST_DOUBLE_PARSER(false),

USE_FAST_DOUBLE_PARSER默认关闭,该特性决定了在解析双精度浮点数(doubles)时是否使用内置的Double#parseDouble(String)方法,还是使用FastDoubleParser实现。出于向后兼容性的考虑,这个特性默认是禁用的。开发者可以根据性能需求和兼容性要求来决定是否启用这个特性。

          USE_FAST_BIG_NUMBER_PARSER(false)

USE_FAST_DOUBLE_PARSER默认关闭,该特性决定了在解析BigDecimalBigInteger时是否使用Java内置的解析代码,还是使用特别优化的自定义实现。为了保持向后兼容性,这个特性默认是禁用的。开发者可以根据性能需求和兼容性要求来决定是否启用这个特性。

3. 配置特征

接下来我们了解下以JsonFactory为例演示如何配置特征,JsonGeneratorJsonParser使用方式也一样,主要分为开启、关闭、配置、查询等几类API

通过configure方法可以开启或关闭某个特性,该方法有两个参数,一个是特性枚举类,一个是开启或关闭,可以看到JsonFactory支持配置多种类型的特性枚举: image.png 通过enable方法可以开启某个特性: image.png 通过disable方法可以关闭某个特性: image.png 通过isEnabled方法可以查询某个特征的开启状态:: image.png 使用new JsonFactory (不推荐)示例代码:

        JsonFactory jsonFactory = new JsonFactory();
        jsonFactory.configure(JsonFactory.Feature.INTERN_FIELD_NAMES,true); // 配置特性(已过时)推荐使用 JsonFactory.builder()
        jsonFactory.enable(JsonFactory.Feature.INTERN_FIELD_NAMES); // 开启特性(已过时)
        jsonFactory.disable(JsonFactory.Feature.INTERN_FIELD_NAMES); // 关闭特性(已过时)

使用JsonFactory.builder (推荐)示例代码:

        JsonFactory jsonFactory = JsonFactory.builder()
                .configure(JsonFactory.Feature.INTERN_FIELD_NAMES, true)// 配置特性
                .enable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES)// 开启特性
                .disable(JsonFactory.Feature.CHARSET_DETECTION)// 关闭特性
                .build();