Jackson 2.x 系列【17】序列化器提供者 SerializerProvider

534 阅读5分钟

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

本系列 Jackson 版本 2.17.0

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

1. 概述

ObjectMapper在执行过程中,需要获取到对应类型的序列化器或反序列化器,然后执行具体操作。例如在序列化时List<T>,需要获取可以序列化List<T>类型的JsonSerializer(序列化器)。

这时需要使用到SerializerProvider,它是一个负责提供特定类型序列化器的抽象类,并实现了缓存功能。

2. DatabindContext

DatabindContext翻译过来是数据绑定上下文的意思,该抽象类声明了多个获取上下文相关信息的抽象方法,也提供了多个可以直接使用的普通⽅法供子类直接调用。

DatabindContext有两个重要的实现子类,它们是用于数据绑定过程中的关键上下文对象:

image.png

声明了多个用于获取配置的抽象方法:

    /**
     * 获取 MapperConfig
     */
    public abstract MapperConfig<?> getConfig();

    /**
     * 获取 AnnotationIntrospector
     */
    public abstract AnnotationIntrospector getAnnotationIntrospector();

    // 查询某个MapperFeature 是否开启
    public abstract boolean isEnabled(MapperFeature feature);

    // 查询某个DatatypeFeature 是否开启
    public abstract boolean isEnabled(DatatypeFeature feature);

    // 获取 DatatypeFeatures
    public abstract DatatypeFeatures getDatatypeFeatures();

    // 查询是否允许覆盖访问修饰符
    public abstract boolean canOverrideAccessModifiers();

    // 获取当前正在使用的视图对象
    public abstract Class<?> getActiveView();

    // 获取当前正在使用的Locale
    public abstract Locale getLocale();

    // 获取当前正在使用的TimeZone
    public abstract TimeZone getTimeZone();

    // 获取@JsonFormat标注的信息
    public abstract JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType);

用于在上下文中设置和获取属性的抽象方法:

    /**
     * 获取上下文中可用的属性,每次调用的属性具有最高优先级,通过 {@link ObjectReader} 或 {@link ObjectWriter} 设置的属性具有较低的优先级。
     *
     * @param key 要获取的属性的键
     * @return 如果存在,则返回属性的值;否则返回null
     * @since 2.3
     */
    public abstract Object getAttribute(Object key);


    /**
     * 上下文中设置属性,会覆盖之前的
     *
     * @param key   要设置的属性的键
     * @param value 要设置的属性值
     * @return 此上下文对象,以支持链式调用
     * @since 2.3
     */
    public abstract DatabindContext setAttribute(Object key, Object value);

JavaTypeJackson中用于表示Java类型信息的类,用于在序列化和反序列化JSON时正确处理不同类型的Java对象。 DatabindContext提供了将JDK类型转为JavaType的普通方法:

    public JavaType constructType(Type type) {
        if (type == null) {
            return null;
        }
        return getTypeFactory().constructType(type);
    }

提供了多个类型实例化和解析过程中,需要处理泛型擦除、多态的普通方法:

    // 在构建过程中会保留泛型(避免泛型擦除)来构建子类型
    public abstract JavaType constructSpecializedType(JavaType baseType, Class<?> subclass);

    // 多态处理过程中,解析出子类的类名
    public JavaType resolveSubType(JavaType baseType, String subClassName) throws JsonMappingException {
        // ........
    }

    // 多态处理抛出异常
    protected <T> T _throwNotASubtype(JavaType baseType, String subType) throws JsonMappingException {
        throw invalidTypeIdException(baseType, subType, "Not a subtype");
    }
    protected <T> T _throwSubtypeNameNotAllowed(JavaType baseType, String subType, PolymorphicTypeValidator ptv) throws JsonMappingException {
        // ........
    }
    protected <T> T _throwSubtypeClassNotAllowed(JavaType baseType, String subType, PolymorphicTypeValidator ptv) throws JsonMappingException {
        // ........
    }

3. SerializerProvider

SerializerProvider继承自DatabindContext,也是一个抽象类,ObjectMapperJsonSerializers通过它获取特定类型的序列化器,并实现了缓存功能,当多次需要同一类型的序列化器时,先从缓存中查询。

3.1 成员属性

SerializerProvider提供了很多成员属性:

    // 未知的映射是否进行缓存,可以加快解析速度
    protected final static boolean CACHE_UNKNOWN_MAPPINGS = false;

    // 默认的 Map 中的 Null 键序列化器,会直接抛出异常
    public final static JsonSerializer<Object> DEFAULT_NULL_KEY_SERIALIZER =
        new FailingSerializer("Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)");

    // 用于处理java.lang.Object类型属性的默认序列化器
    protected final static JsonSerializer<Object> DEFAULT_UNKNOWN_SERIALIZER = new UnknownSerializer();

    // 序列化配置
    protected final SerializationConfig _config;

    // 视图
    protected final Class<?> _serializationView;

    // 用于构建序列化器实例的工厂
    protected final SerializerFactory _serializerFactory;

    // 序列化器缓存
    protected final SerializerCache _serializerCache;

    // 上下文属性
    protected transient ContextAttributes _attributes;

    // 未知类型的序列化器,默认的会抛出异常
    protected JsonSerializer<Object> _unknownTypeSerializer = DEFAULT_UNKNOWN_SERIALIZER;

    // Map 中键的序列化器
    protected JsonSerializer<Object> _keySerializer;

    // null 值序列化器,默认调用 JsonGenerator#writeNull
    protected JsonSerializer<Object> _nullValueSerializer = NullSerializer.instance;

    // Map 中的 Null 键的序列化器,默认的会抛出异常
    protected JsonSerializer<Object> _nullKeySerializer = DEFAULT_NULL_KEY_SERIALIZER;

    // 本地非共享、只读的一个MAP,用于快速查找之前已经获取过的序列化器
    protected final ReadOnlyClassToSerializerMap _knownSerializers;

    // 日期格式化器
    protected DateFormat _dateFormat;

    // 是否使用的是标准的 NullValueSerializer
    protected final boolean _stdNullValueSerializer;

3.2 构造方法

SerializerProvider的构造方法,主要是对成员属性进行赋值:

    public SerializerProvider()
    {
        _serializerCache = new SerializerCache();
        // 省略...........
        _stdNullValueSerializer = true;
    }

    protected SerializerProvider(SerializerProvider src,
            SerializationConfig config, SerializerFactory f)
    {
        // 省略...........
        _stdNullValueSerializer = (_nullValueSerializer == DEFAULT_NULL_KEY_SERIALIZER);
        _knownSerializers = _serializerCache.getReadOnlyLookupMap();
    }

3.3 setter & getter & isXx

我们在构建JsonMapperObjectMapper对象后,可以获取SerializerProvider对象,然后调用setter/getter/isXx方法。

示例代码:

        JsonMapper jsonMapper = JsonMapper.builder().build();
        SerializerProvider serializerProvider = jsonMapper.getSerializerProvider();
        JsonSerializer<Object> defaultNullValueSerializer = serializerProvider.getDefaultNullValueSerializer(); // 获取默认的null 值序列化器

getter方法获取成员属性: image.png setter方法设置属性: image.png

isXx方法查询:

image.png

3.4 findXx

提供了多个findXx方法用于查询序列化器: image.png

3.5 defaultXx

提供了多个defaultXx用于默认的特定类型的序列化处理: image.png

3.5 reportXx

提供了多个reportXx用于抛出序列化异常:

image.png

4. DefaultSerializerProvider

DefaultSerializerProviderSerializerProvider的标准抽象实现,所有自定义的SerializerProvider实现都必须基于这个类。

DefaultSerializerProvider中已经提供了调用序列化器执行操作的可用方法: image.png

提供了一个可用的Impl内部类,可以看到它基本没有什么处理逻辑,都交给了抽象类去完成:

    public final static class Impl extends DefaultSerializerProvider {
        private static final long serialVersionUID = 1L;

        public Impl() { super(); }
        public Impl(Impl src) { super(src); }

        protected Impl(SerializerProvider src, SerializationConfig config,
                SerializerFactory f) {
            super(src, config, f);
        }

        /**
         * @since 2.16
         */
        protected Impl(Impl src, CacheProvider cp) {
            super(src, cp);
        }

        @Override
        public DefaultSerializerProvider copy()
        {
            return new Impl(this);
        }

        @Override
        public Impl createInstance(SerializationConfig config, SerializerFactory jsf) {
            return new Impl(this, config, jsf);
        }

        @Override
        public DefaultSerializerProvider withCaches(CacheProvider cp) {
            return new Impl(this, cp);
        }
    }
}

5. DeserializationContext

这里简单提一下DeserializationContext,因为它的继承结构、方法、属性等都和SerializerProvider差不多,不过是用于反序列化处理。

image.png