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

news2024/11/25 2:25:24

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

本系列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);
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSDN 广告太多,停更通知,转移到博客园

文章目录 前言新博客地址 前言 CSDN的广告实在是太多了&#xff0c;我是真的有点忍不了。直接把广告插在我的文章中间。而且我已经懒得找工作了&#xff0c;我当初写CSDN的目的就是为了找工作&#xff0c;有个博客排名。当时经济环境实在是太差了。我也没必要纠结这个2000粉丝…

Vue通过自定义指令实现元素平滑上升的动画效果。没一句废话

1、演示 2、介绍 这个指令不是原生自带的&#xff0c;需要手动去书写&#xff0c;但是这辈子只需要编写这一次就好了&#xff0c;后边可以反复利用。 用到的API&#xff1a;IntersectionObserver 这里有详细介绍 3、Vue文件代码 <template><div class"container&…

【计算机考研】408算法大题怎么练?

先说结论&#xff1a;基础阶段学好各个数据结构与&#xff0c;重点是数组、链表、树、图。然后强化阶段突破算法提 在基础阶段&#xff0c;并不需要过于专门地练习算法。相反&#xff0c;基础阶段的重点应该放在对各种数据结构原理的深入理解上。在我个人的经验中&#xff0c;…

【AcWing】蓝桥杯集训每日一题Day17|单调队列|求直方图中最大矩形|单调栈|模型转化|1413.矩形牛棚(C++)

1413.矩形牛棚 1413. 矩形牛棚 - AcWing题库难度&#xff1a;中等时/空限制&#xff1a;1s / 256MB总通过数&#xff1a;1914总尝试数&#xff1a;3823来源&#xff1a;usaco training 6.1算法标签单调栈 题目内容 作为一个资本家&#xff0c;农夫约翰希望通过购买更多的奶牛…

【零基础学数据结构】链表

目录 1.链表的概念 ​编辑 2.链表的雏形 ​编辑 3.链表的组成 ​编辑 4.链表代码 4.1创建节点 4.2链表的打印 4.3链表的尾插 4.4链表的头插 4.5链表的尾删 4.6链表的头删 4.7链表的查找 4.8链表在指定位置之前插⼊数据 4.9链表在指定位置之后插⼊数据 4.9-1删除pos节点 4.9…

VBA技术资料MF140:在PowerPoint中移动幻灯片位置

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

Java基于微信小程序的校园外卖平台设计与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

openGauss学习笔记-255 openGauss性能调优-使用Plan Hint进行调优-Hint的错误、冲突及告警

文章目录 openGauss学习笔记-255 openGauss性能调优-使用Plan Hint进行调优-Hint的错误、冲突及告警 openGauss学习笔记-255 openGauss性能调优-使用Plan Hint进行调优-Hint的错误、冲突及告警 Plan Hint的结果会体现在计划的变化上&#xff0c;可以通过explain来查看变化。 …

公开课学习——JVM虚拟机面试核心点与性能优化点

文章目录 jdk的体系结构图Java语言的跨平台的特性&#xff0c;怎么实现的&#xff1f;jvm内部组成呢&#xff1f;pc的值怎么变得&#xff1f;main方法的栈帧有一点点区别&#xff0c;Math()是new出来的&#xff0c;放在堆区&#xff0c;这个堆区的math和我们栈帧中的局部变量表…

SpringBoot之集成Redis

SpringBoot之集成Redis 一、Redis集成简介二、集成步骤2.1 添加依赖2.2 添加配置2.3 项目中使用 三、工具类封装四、序列化 &#xff08;正常都需要自定义序列化&#xff09;五、分布式锁 一、Redis集成简介 Redis是我们Java开发中&#xff0c;使用频次非常高的一个nosql数据库…

【频繁模式挖掘】Apriori算法(附Python实现)

一、实验内容简介 该实验主要使用频繁模式和关联规则进行数据挖掘&#xff0c;使用Apriori算法和Python语言来编写和设计程序&#xff0c;然后用不同规模的数据集来检验效果&#xff0c;最后分析和探讨实验结果&#xff0c;看其是否达到了理想的效果。 二、算法说明 关联规则…

2024年生成式人工智能的现状:进展、挑战与未来展望的深入分析

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

wireshark抓包新手使用教程

Wireshark是非常流行的网络封包分析软件&#xff0c;可以截取各种网络数据包&#xff0c;并显示数据包详细信息。常用于开发测试过程各种问题定位。本文主要内容包括&#xff1a; 1、Wireshark软件下载和安装以及Wireshark主界面介绍。 2、WireShark简单抓包示例。通过该例子学…

【C++航海王:追寻罗杰的编程之路】探寻实用的调试技巧

目录 1 -> 什么是bug&#xff1f; 2 -> 调试是什么&#xff1f;有多重要&#xff1f; 2.1 -> 调试是什么&#xff1f; 2.2 -> 调试的基本步骤 2.3 -> Debug和Release的介绍 3 -> Windows环境调试介绍 3.1 -> 调试环境的准备 3.2 -> 学会快捷键…

不牺牲算法,不挑剔芯片,这个来自中科院的团队正在加速国产AI芯片破局

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 不降低大模型算法精度&#xff0c;还能把芯片的算力利用效率提升 2~10 倍&#xff0c;这就是…

java swing毕业设计题目管理系统eclipse开发Mysql数据库CS结构java编程

一、源码特点 java swing毕业设计题目管理系统 是一套完善的窗体设计系统&#xff0c;对理解SWING java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;&#xff0c;系统主要采用C/S模式开发。 应用技术&#xff1a;javamysql 开发工具&#xff…

杨笛一新作:社恐有救了,AI大模型一对一陪聊,帮i人变成e人

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站ai人工智能工具 更多资源欢迎关注 在社交活动中&#xff0c;大语言模型既可以是你的合作伙伴&#xff08;partner&#xff09;&#xff0…

SSL证书价格为什么差异如此大?

SSL证书市场品牌和种类众多&#xff0c;用户在选择证书的时候&#xff0c;也能随心所欲的购买到心仪的证书品牌类型。但是也有不少用户在选购的时候&#xff0c;也不禁有疑问&#xff1a;不同的证书品牌和类型为什么价格相差如此之大&#xff1f;确实&#xff0c;有的证书很便宜…

重磅来袭!2024CWE北京门窗幕墙展

CWE中国&#xff08;北京&#xff09;国际系统门窗及幕墙博览会 CWE China&#xff08;Beijing&#xff09;International System Doors Windows and Curtain Walls Expo 2024 年 8 月 29-31 日 北京&#xff0c;中国国际展览中心顺义馆 展会概况&#xff1a; 2024年CWE中国…

低代码开发平台推荐:国内超好用的十款实测评测

随着互联网技术的飞速发展&#xff0c;低代码平台逐渐成为企业数字化转型的利器。这类平台简化了开发过程&#xff0c;让非专业开发者也能参与到应用构建中来。本文将为您盘点国内十大低代码平台有&#xff1a;Zoho creator、&#xff0c;帮助您更好地选择适合自己企业的低代码…