Jackson 2.x 系列【15】序列化器 JsonSerializer

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

本系列Jackson 版本 2.17.0

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

文章目录

    • [1. 概述](#1. 概述)
    • [2. 方法](#2. 方法)
      • [2.1 构造](#2.1 构造)
      • [2.2 序列化](#2.2 序列化)
      • [2.3 其他](#2.3 其他)
    • [3. 实现类](#3. 实现类)
      • [3.1 StdSerializer](#3.1 StdSerializer)
        • [3.1.1 源码](#3.1.1 源码)
        • [3.1.2 ContainerSerializer](#3.1.2 ContainerSerializer)
        • [3.1.3 ToStringSerializerBase](#3.1.3 ToStringSerializerBase)
        • [3.1.4 NullSerializer](#3.1.4 NullSerializer)
        • [3.1.5 BeanSerializerBase](#3.1.5 BeanSerializerBase)
      • [3.2 None](#3.2 None)
      • [3.3 TypeWrappedSerializer](#3.3 TypeWrappedSerializer)

1. 概述

JsonSerializer是一个用于序列化Java对象为JSON的抽象类,是Jackson中的重要组件之一。

2. 方法

JsonSerializer没有成员属性,但是声明了很多方法。

2.1 构造

Fluent风格的工厂方法用于构建经过装饰或增强的序列化器对象。

java 复制代码
    /**
     * 未包装的序列化器对象
     *
     * @param unwrapper 用于在包装器属性名称之间转换的名称转换器
     */
    public JsonSerializer<T> unwrappingSerializer(NameTransformer unwrapper) {
        return this;
    }

    /**
     * 用于尝试替换此序列化器所委托调用的序列化器,如果不支持,则应抛出 {@link UnsupportedOperationException}或者直接返回此序列化器本身。
     *
     * @since 2.1
     */
    public JsonSerializer<T> replaceDelegatee(JsonSerializer<?> delegatee) {
        throw new UnsupportedOperationException();
    }

    /**
     * 支持过滤的子类,如果过滤器发生变化,则需要创建并返回新的实例。
     *
     * @since 2.6
     */
    public JsonSerializer<?> withFilterId(Object filterId) {
        return this;
    }

    /**
     * 用于在排除指定名称的属性集后创建新的实例(如果存在的话)
     *
     * @param ignoredProperties  忽略序列化的一组属性名称
     * @return 序列化器实例,它不会忽略指定的属性集(如果存在的话)
     * @since 2.16
     */
    public JsonSerializer<?> withIgnoredProperties(Set<String> ignoredProperties) {
        return this;
    }

2.2 序列化

序列化是将对象状态转换为可以存储或传输的形式的过程,JsonGenerator声明了两个序列化方法,这是我们需要关注的重点。

java 复制代码
    /**
     * 序列化
     *
     * @param value       要序列化的值,不能为null
     * @param gen         用于输出Json内容的生成器
     * @param serializers 提供者,可用于获取序列化包含在值中的对象所需的序列化器(如果有的话)
     */
    public abstract void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException;

    /**
     * 使用指定的类型序列化器来序列化
     *
     * @param value       要序列化的值,不能为null
     * @param gen         用于输出Json内容的生成器
     * @param serializers 提供者,可用于获取序列化包含在值中的对象所需的序列化器(如果有的话)
     * @param typeSer     指定的类型序列化器
     */
    public void serializeWithType(T value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
        Class<?> clz = handledType();
        if (clz == null) {
            clz = value.getClass();
        }
        serializers.reportBadDefinition(clz, String.format("Type id handling not implemented for type %s (by serializer of type %s)", clz.getName(), getClass().getName()));
    }

2.3 其他

其他的一些方法,了解即可。

java 复制代码
    /**
     * 获取序列化器可以处理的对象类型
     */
    public Class<T> handledType() {
        return null;
    }

    /**
     * 检查可序列化值是否被视为"空"值(用于抑制空值的序列化)。
     *
     * @deprecated 自2.5版本起,请使用 {@link #isEmpty(SerializerProvider, Object)} 替代,在3.0版本中将被移除。
     */
    @Deprecated
    public boolean isEmpty(T value) {
        return isEmpty(null, value);
    }

    /**
     * 检查可序列化值是否被视为"空"值(用于抑制空值的序列化)。
     *
     * @since 2.5
     */
    public boolean isEmpty(SerializerProvider provider, T value) {
        return (value == null);
    }

    /**
     * 查询此序列化器实例是否将使用ObjectId来处理循环引用。
     */
    public boolean usesObjectId() {
        return false;
    }

    /**
     * 用于检查此序列化器是否为"解包"序列化器
     */
    public boolean isUnwrappingSerializer() {
        return false;
    }

    /**
     * 用于确定此序列化器是否通过使用另一个序列化器进行实际序列化(通过委托调用),如果是,则返回该序列化器,否则返回null。
     *
     * @since 2.1
     */
    public JsonSerializer<?> getDelegatee() {
        return null;
    }

    /**
     * 迭代此序列化器所处理类型的逻辑属性。
     *
     * @since 2.6
     */
    public Iterator<PropertyWriter> properties() {
        return ClassUtil.emptyIterator();
    }
    
    /**
     * 默认实现只是调用 {@link JsonFormatVisitorWrapper#expectAnyFormat(JavaType)}。
     *
     * @since 2.1
     */
    @Override
    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType type) throws JsonMappingException {
        visitor.expectAnyFormat(type);
    }

3. 实现类

JsonSerializer有很多的实现类,用于处理各种数据类型。

3.1 StdSerializer

StdSerializer即标准的序列化器,也是一个抽象类,是在JsonSerializer的基础上封装了一些通用方法,实现序列化器时,应该继承该类,而不是JsonSerializer

3.1.1 源码

StdSerializer声明了两个成员属性和一些构造方法:

java 复制代码
    /**
     * 用于存储锁对象的键,以防止在构造转换序列化器时发生无限递归
     *
     * @since 2.9
     */
    private final static Object KEY_CONTENT_CONVERTER_LOCK = new Object();

    /**
     * 支持的类型,通常是所使用的序列化器对应属性的声明类型。
     */
    protected final Class<T> _handledType;

    protected StdSerializer(Class<T> t) {
        _handledType = t;
    }

    @SuppressWarnings("unchecked")
    protected StdSerializer(JavaType type) {
        _handledType = (Class<T>) type.getRawClass();
    }

    /**
     *  用来解决泛型类型处理中的一些问题
     */
    @SuppressWarnings("unchecked")
    protected StdSerializer(Class<?> t, boolean dummy) {
        _handledType = (Class<T>) t;
    }

    /**
     * @since 2.6
     */
    @SuppressWarnings("unchecked")
    protected StdSerializer(StdSerializer<?> src) {
        _handledType = (Class<T>) src._handledType;
    }

核心的序列化方法任然是抽象的,需要子类去实现:

java 复制代码
    @Override
    public abstract void serialize(T value, JsonGenerator gen, SerializerProvider provider)
            throws IOException;

提供了很多辅助方法,供子类调用,例如用于标识底层JSON类型的方法:

java 复制代码
    /**
     * 辅助方法,用于调用必要的访问方法,以指示底层JSON类型为JSON字符串。
     *
     * @since 2.7
     */
    protected void visitStringFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint)
            throws JsonMappingException {
        /*JsonStringFormatVisitor v2 =*/
        visitor.expectStringFormat(typeHint);
    }

    /**
     * 辅助方法,用于调用必要的访问方法,以指示底层JSON类型为JSON字符串,但存在更精细的逻辑类型。
     *
     * @since 2.7
     */
    protected void visitStringFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint,
                                     JsonValueFormat format)
            throws JsonMappingException {
        JsonStringFormatVisitor v2 = visitor.expectStringFormat(typeHint);
        if (v2 != null) {
            v2.format(format);
        }
    }

    /**
     * 辅助方法,用于调用必要的访问方法,以指示底层JSON类型为JSON整数。
     *
     * @since 2.7
     */
    protected void visitIntFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint,
                                  NumberType numberType)
            throws JsonMappingException {
        JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint);
        if (_neitherNull(v2, numberType)) {
            v2.numberType(numberType);
        }
    }

    /**
     * 辅助方法,用于调用必要的访问方法,以指示底层JSON类型为JSON整数,但还涉及进一步的格式限制。
     *
     * @since 2.7
     */
    protected void visitIntFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint,
                                  NumberType numberType, JsonValueFormat format)
            throws JsonMappingException {
        JsonIntegerFormatVisitor v2 = visitor.expectIntegerFormat(typeHint);
        if (v2 != null) {
            if (numberType != null) {
                v2.numberType(numberType);
            }
            if (format != null) {
                v2.format(format);
            }
        }
    }

    /**
     * 辅助方法,用于调用必要的访问方法,以指示底层JSON类型为浮点型JSON数字。
     *
     * @since 2.7
     */
    protected void visitFloatFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint,
                                    NumberType numberType)
            throws JsonMappingException {
        JsonNumberFormatVisitor v2 = visitor.expectNumberFormat(typeHint);
        if (v2 != null) {
            v2.numberType(numberType);
        }
    }

    /**
     * @since 2.7
     */
    protected void visitArrayFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint,
                                    JsonSerializer<?> itemSerializer, JavaType itemType)
            throws JsonMappingException {
        JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
        if (_neitherNull(v2, itemSerializer)) {
            v2.itemsFormat(itemSerializer, itemType);
        }
    }

    /**
     * @since 2.7
     */
    protected void visitArrayFormat(JsonFormatVisitorWrapper visitor, JavaType typeHint,
                                    JsonFormatTypes itemType)
            throws JsonMappingException {
        JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
        if (v2 != null) {
            v2.itemsFormat(itemType);
        }
    }

用于包装处理异常的辅助方法:

java 复制代码
   public void wrapAndThrow(SerializerProvider provider,
                             Throwable t, Object bean, String fieldName)
            throws IOException { //..............}
            
   public void wrapAndThrow(SerializerProvider provider,
                             Throwable t, Object bean, int index)
            throws IOException {//..............}

和注解相关的辅助方法:

java 复制代码
    /**
     * 用于检查指定的属性是否具有指示需要对包含的值(结构化类型的内容;数组/列表/映射值)使用转换器的注解。
     */
    protected JsonSerializer<?> findContextualConvertingSerializer(SerializerProvider provider,
                                                                   BeanProperty property, JsonSerializer<?> existingSerializer)
            throws JsonMappingException { //..............}
            
    /**
     * 根据 ID 查询 PropertyFilter
     */
    protected PropertyFilter findPropertyFilter(SerializerProvider provider,
                                                Object filterId, Object valueToFilter)
            throws JsonMappingException {//..............}

    /**
     * 辅助方法,可用于查找此反序列化器是否具有特定的 {@link JsonFormat} 设置
     */
    protected JsonFormat.Value findFormatOverrides(SerializerProvider provider,
                                                   BeanProperty prop, Class<?> typeForDefaults) {//..............}

    /**
     * 查找JsonFormat.Feature特性是否已被特别标记为启用或禁用
     */
    protected Boolean findFormatFeature(SerializerProvider provider,
                                        BeanProperty prop, Class<?> typeForDefaults, JsonFormat.Feature feat) {//..............}
                                        
    /**
     * 查找是否包含@JsonInclude.Value
     */
    protected JsonInclude.Value findIncludeOverrides(SerializerProvider provider,
                                                     BeanProperty prop, Class<?> typeForDefaults) {//..............}
    /**
     * 辅助方法,用于查找可能已配置的内容值序列化器。
     */
    protected JsonSerializer<?> findAnnotatedContentSerializer(SerializerProvider serializers,
                                                               BeanProperty property)
            throws JsonMappingException {//..............}
3.1.2 ContainerSerializer

Jackson默认提供了很多StdSerializer的实现类:

这里挑出一些常用的进行讲解,首先是ContainerSerializer,可以直接看出是用于集合类型的序列化:

示例,在序列化List<T>时,调用的是IndexedListSerializer

java 复制代码
        JsonMapper jsonMapper = JsonMapper.builder().build();
        List<String> list=new ArrayList<>();
        list.add("haha");
        list.add("heihei");
        String jsonValue = jsonMapper.writeValueAsString(list);
        System.out.println(jsonValue);
3.1.3 ToStringSerializerBase

ToStringSerializerBase用于将值序列化为字符串,支持BigDecimalZoneIdString类型:

3.1.4 NullSerializer

NullSerializer用于序列化null值,可以看到直接调用了JsonGenerator.writeNull()方法,JSON中直接使用null表示:

java 复制代码
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeNull();
    }

    public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
        gen.writeNull();
    }
3.1.5 BeanSerializerBase

BeanSerializerBase是一个用于序列化JavaBean对象的基础类,提供了一些可重用且可扩展的方法,开发者可以只注重于实现自定义的序列化逻辑。

BeanSerializerBase会处理 JavaBean 的一些通用特性,如属性的访问(通过 gettersetter 方法)、属性的过滤(基于注解或其他配置)、属性的排序等。

其包含了几个实现类,其中BeanSerializer是标准实现:

3.2 None

NoneJsonSerializer的一个内部抽象类,用于标识@JsonSerialize注解,明确表示不使用任何特定的序列化器,而是使用默认的序列化机制。

java 复制代码
/**
 * 注解 {@link com.fasterxml.jackson.databind.annotation.JsonSerialize} 的标记
 */
public abstract static class None extends JsonSerializer<Object> {
}

@JsonSerialize中可以看到默认用的None,表示没有指定序列化器(使用默认的):

java 复制代码
@JacksonAnnotation
public @interface JsonSerialize {
    Class<? extends JsonSerializer> using() default JsonSerializer.None.class;
    //.......

3.3 TypeWrappedSerializer

TypeWrappedSerializer类型包装序列化器,可以看到有一个TypeSerializer 和一个JsonSerializer属性,序列化都是调用JsonSerializerserializeWithType方法。

很好理解,这是一个包装模式,包装JsonSerializer使用指定的TypeSerializer 进行序列化。

java 复制代码
	protected final TypeSerializer _typeSerializer;
	
    protected final JsonSerializer<Object> _serializer;

    public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException {
        this._serializer.serializeWithType(value, g, provider, this._typeSerializer);
    }

    public void serializeWithType(Object value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException {
        this._serializer.serializeWithType(value, g, provider, typeSer);
    }
相关推荐
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭5 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
李小白665 小时前
Spring MVC(上)
java·spring·mvc
Lojarro8 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
zjw_rp8 小时前
Spring-AOP
java·后端·spring·spring-aop
nbsaas-boot11 小时前
探索 JSON 数据在关系型数据库中的应用:MySQL 与 SQL Server 的对比
数据库·mysql·json
撒呼呼11 小时前
# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)
数据库·spring boot·spring·mvc·springboot
天使day12 小时前
SpringMVC
java·spring·java-ee
疯一样的码农13 小时前
Jackson 的@JsonRawValue
json
壹佰大多14 小时前
【spring-cloud-gateway总结】
java·spring·gateway
CodeChampion14 小时前
60.基于SSM的个人网站的设计与实现(项目 + 论文)
java·vue.js·mysql·spring·elementui·node.js·mybatis