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);
    }
相关推荐
qq_三哥啊2 小时前
【IDEA】设置Debug调试时调试器不进入特定类(Spring框架、Mybatis框架)
spring·intellij-idea·mybatis
别惹CC3 小时前
Spring AI 进阶之路01:三步将 AI 整合进 Spring Boot
人工智能·spring boot·spring
寒士obj3 小时前
Spring事物
java·spring
IT毕设实战小研12 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
甄超锋13 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
Java小白程序员16 小时前
Spring Framework:Java 开发的基石与 Spring 生态的起点
java·数据库·spring
甄超锋17 小时前
Java Maven更换国内源
java·开发语言·spring boot·spring·spring cloud·tomcat·maven
还是鼠鼠18 小时前
tlias智能学习辅助系统--Maven 高级-私服介绍与资源上传下载
java·spring boot·后端·spring·maven
还是大剑师兰特19 小时前
Spring面试题及详细答案 125道(1-15) -- 核心概念与基础1
spring·大剑师·spring面试题·spring教程
python_1361 天前
web请求和响应
java·spring·github