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

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

本系列Jackson 版本 2.17.0

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

文章目录

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

1. 概述

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

2. 方法

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

2.1 构造

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

    /**
     * 未包装的序列化器对象
     *
     * @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声明了两个序列化方法,这是我们需要关注的重点。

    /**
     * 序列化
     *
     * @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 其他

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

    /**
     * 获取序列化器可以处理的对象类型
     */
    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声明了两个成员属性和一些构造方法:

    /**
     * 用于存储锁对象的键,以防止在构造转换序列化器时发生无限递归
     *
     * @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;
    }

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

    @Override
    public abstract void serialize(T value, JsonGenerator gen, SerializerProvider provider)
            throws IOException;

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

    /**
     * 辅助方法,用于调用必要的访问方法,以指示底层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);
        }
    }

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

   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 {//..............}

和注解相关的辅助方法:

    /**
     * 用于检查指定的属性是否具有指示需要对包含的值(结构化类型的内容;数组/列表/映射值)使用转换器的注解。
     */
    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

        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表示:

    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注解,明确表示不使用任何特定的序列化器,而是使用默认的序列化机制。

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

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

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

3.3 TypeWrappedSerializer

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

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

	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);
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/525943.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

说说TCP为什么需要三次握手和四次挥手?

一、三次握手 三次握手&#xff08;Three-way Handshake&#xff09;其实就是指建立一个TCP连接时&#xff0c;需要客户端和服务器总共发送3个包 主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备 过程如下&#xff…

12 | 排序(下):如何用快排思想在O(n)内查找第K大元素?归并排序和快速排序

 下载APP  12 | 排序&#xff08;下&#xff09;&#xff1a;如何用快排思想在O(n)内查找第K大元素&#xff1f; 2018-10-17 王争数据结构与算法之美进入课程 讲述&#xff1a;修阳 时长21:58大小8.81M  上一节我讲了冒泡排序、插入排序、选择排序这三种排序算法&…

Linux系统软件安装

实战&#xff1a;在Linux上部署各类软件 MySQL数据库管理系统安装部署【简单】 简介 MySQL数据库管理系统&#xff08;后续简称MySQL&#xff09;&#xff0c;是一款知名的数据库系统&#xff0c;其特点是&#xff1a;轻量、简单、功能丰富。 MySQL数据库可谓是软件行业的明…

数据库不用mmap

你确定你想用 MMAP 实现数据库么&#xff1f;_哔哩哔哩_bilibili MMAP 的随机读与顺序读的性能表现不好&#xff0c;以及对于写主要是不可控的刷入时机以及代码冗余&#xff0c;所以 MMAP 不适合在数据库中使用。 mmap是posix系统调用&#xff0c;它提供由操作系统管理内存映…

el-date-picker禁用指定范围的日期

elementUI中el-date-picker禁用指定日期之前或之后的日期 通过配置picker-options配置指定禁用日期&#xff08;pickerOptions写到data里面&#xff09; <el-date-pickerv-model"date"type"date"size"small"value-format"yyyy-MM-dd&qu…

怎么显示文件后缀名?这4个策略很赞!

“在查看文件时&#xff0c;我总是无法看到文件的后缀名&#xff0c;有时候我都分辨不出它是什么文件&#xff0c;有朋友知道怎么显示文件后缀名吗&#xff1f;” 在日常使用电脑的过程中&#xff0c;文件后缀名扮演着重要的角色&#xff0c;它可以帮助我们识别文件的类型&…

C——找单身狗2

题目内容&#xff1a; 在一个数组中&#xff0c;室友两个数字出现了一次&#xff0c;其他所有数字都出现了两次。找出只出现一次的数字。 如&#xff1a;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff…

【ZBrush】制作章鱼练习 01——头部

目录 本篇效果 步骤 一、准备工作 二、制作头部外形 三、制作眼睛 本篇效果 步骤 一、准备工作 我们需要制作的模型如下 首先创建一个球体 点击编辑对象 点击“生成 多边形网格物体” 选择“MatCap Gray”材质&#xff0c;颜色设置为白色 要打开“Mrgb”通道和“绘制”选…

Vue - 你知道Vue组件中的data为什么是一个函数吗

难度级别:中高级及以上 提问概率:80% 在Vue项目中,App.vue下的每个子组件都会生成一个单独的Vue实例对象,但这些子对象都是通过通过vue.extend方法创建而来的,也就是说我们平时在项目中所定义的Vue组件,都有一个相同的父类对象。这样也就…

CSS 基础:设置背景的 5 个属性及简写 background 注意点

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合集 263篇…

实时计算平台设计方案:911-基于6U VPX的光纤图像DSP实时计算平台

基于6U VPX的光纤图像DSP实时计算平台 一、系统组成 该平台基于风冷式的 6U 6槽VPX图像处理平台&#xff0c;包括&#xff1a;计算机主板、计算机主板后板、存储板、图像信号处理板、图像信号处理板后板、图像光纤转接板、机箱背板及机箱组成。图1为系统背板结构示意图&…

TechTool Pro for Mac v19.0.3中文激活版 硬件监测和系统维护工具

TechTool Pro for Mac是一款专为Mac用户设计的强大系统维护和故障排除工具。它凭借全面的功能、高效的性能以及友好的操作界面&#xff0c;赢得了广大用户的信赖和好评。 软件下载&#xff1a;TechTool Pro for Mac v19.0.3中文激活版 作为一款专业的磁盘和系统维护工具&#x…

第八讲 Sort Aggregate 算法

我们现在将讨论如何使用迄今为止讨论过的 DBMS 组件来执行查询。 1 查询计划【Query Plan】 我们首先来看当一个查询【Query】被解析【Parsed】后会发生什么&#xff1f; 当 SQL 查询被提供给数据库执行引擎&#xff0c;它将通过语法解析器进行检查&#xff0c;然后它会被转换…

VueRouter的介绍:什么是路由呢?VueRouter的作用及使用,VueRouter的使用分为5个步骤和特定的2步

1.什么是路由呢&#xff1f; 路由就是路径和组件之间的映射关系&#xff0c;当我们路径变化的时候&#xff0c;就要切换对应的组件。 在前端中解决路径与组件之间的映射关系&#xff0c;官方提供了VueRouter这个插件 2.VueRouter的作用及使用 作用&#xff1a;修改地址栏路…

基于单片机手机屏蔽器系统仿真设计

**单片机设计介绍&#xff0c;基于单片机手机屏蔽器系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机手机屏蔽器系统的仿真设计主要涉及到手机信号屏蔽的原理、单片机控制逻辑设计、仿真软件的选择与使用以…

太厉害了,不愧是字节出来的。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 前段时间公司缺人&#xff0c;也面了许多测试&#xff0c;一开始瞄准的就是中级水准&#xff0c…

DolphinScheduler 答案整理,最新面试题

DolphinScheduler的架构设计是怎样的&#xff1f; DolphinScheduler的架构设计主要分为四个层次&#xff1a;前端界面层、API服务层、调度层和执行层。 1、前端界面层&#xff1a; 提供任务的定义、流程的设计、监控等功能&#xff0c;用户通过前端界面操作整个系统。 2、AP…

【AN】简单的实现点击播放影片剪辑再点击暂停的功能

动画故事背景 一个影片剪辑&#xff0c;里面做了一个动画。我希望影片剪辑一开始是暂停的&#xff0c;按钮点击后开始播放&#xff0c;再次点击就暂停&#xff01; 下图那个花瓣就是影片剪辑&#xff0c;里面有个掉落的路径引导动画&#xff01; 1.首先给花瓣影片剪辑一个实例…

恭贺格雷勒管业入围2024进口管道十大品牌

恭贺格雷勒管业入围2024进口管道十大品牌 2024进口管道十大品牌网络评选再次成功举办。格雷勒管道凭借优异的产品质量&#xff0c;再次成功入围。 格雷勒隶属于格勒菲德进出口贸易&#xff08;上海&#xff09;有限公司。德国【格雷勒】在总部德国杜塞尔多夫设置了专业实验室&a…