Jackson 2.x 系列【16】反序列化器 JsonDeserializer

news2025/9/21 20:12:54

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

本系列Jackson 版本 2.17.0

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

文章目录

    • 1. 概述
    • 2. 方法
      • 2.1 构造
      • 2.2 反序列化
      • 2.3 null 处理
      • 2.4 空值
      • 2.5 其他
    • 3. 实现类
      • 3.1 StdDeserializer
        • 3.1.1 成员属性
        • 3.1.2 构造
        • 3.1.3 反序列化
        • 3.1.4 辅助方法
        • 3.1.5 实现类
      • 3.2 None
      • 3.3 TypeWrappedDeserializer
      • 3.4 AbstractDeserializer
      • 3.5 ErrorThrowingDeserializer

1. 概述

JsonDeserializer是一个用于将JSON反序列化为任意类型的对象的抽象类,是Jackson中的重要组件之一。

2. 方法

JsonDeserializer声明了很多方法。

2.1 构造

Fluent风格的工厂方法用于构建经过装饰或增强的对象(和JsonSerializer类似)。

public JsonDeserializer<T> unwrappingDeserializer(NameTransformer unwrapper) {
        return this;
    }
    
public JsonDeserializer<?> replaceDelegatee(JsonDeserializer<?> delegatee) {
        throw new UnsupportedOperationException();
    }

2.2 反序列化

声明了核心的反序列化方法:

    /**
     * 反序列化
     *
     * @param p    Json解析器
     * @param ctxt 反序列化上下文
     * @return 反序列化后的对象
     */
    public abstract T deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JacksonException;

    /**
     * 反序列化
     *
     * @param p    Json解析器
     * @param ctxt 反序列化上下文
     * @param intoValue 已经初始化的值实例
     * @return 反序列化后的对象
     */
    public T deserialize(JsonParser p, DeserializationContext ctxt, T intoValue)
            throws IOException, JacksonException {
        ctxt.handleBadMerge(this);
        return deserialize(p, ctxt);
    }

    /**
     * 反序列化
     *
     * @param p    Json解析器
     * @param ctxt 反序列化上下文
     * @param typeDeserializer 反序列化类型
     * @return 反序列化后的对象
     */
    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
                                      TypeDeserializer typeDeserializer)
            throws IOException, JacksonException {
        // We could try calling
        return typeDeserializer.deserializeTypedFromAny(p, ctxt);
    }

    /**
     * 反序列化
     *
     * @param p    Json解析器
     * @param ctxt 反序列化上下文
     * @param typeDeserializer 反序列化类型
     * @param intoValue 已经初始化的值实例                 
     * @return 反序列化后的对象
     */
    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
                                      TypeDeserializer typeDeserializer, T intoValue)
            throws IOException, JacksonException {
        ctxt.handleBadMerge(this);
        return deserializeWithType(p, ctxt, typeDeserializer);
    }

2.3 null 处理

JSON中的null值在反序列时,需要一种可控和可预测的方式确定应该使用什么值来表示这个null,对于引用类型(如对象或数组),通常直接使用Javanull。但对于原始数据类型(如intdouble等),Java没有null的概念,因此需要一个特殊的策略来处理这种情况。

JsonDeserializer声明了处理null的方法:

    /**
     * 处理null,默认返回null
     */
    @Override
    public T getNullValue(DeserializationContext ctxt) throws JsonMappingException {
        // Change the direction in 2.7
        return getNullValue(); // 返回null
    }

    /**
     * 处理null,getNullValue(DeserializationContext)方法的优化版
     * 当getNullValue返回的值是静态的时,反序列化器可以缓存这个值,避免在每次需要时都重新计算。
     */
    @Override
    public AccessPattern getNullAccessPattern() {
        // Default implementation assumes that the null value does not vary, which
        // is usually the case for most implementations. But it is not necessarily
        // `null`; so sub-classes may want to refine further.
        return AccessPattern.CONSTANT;
    }

    /**
     * 确定在没有从输入中获得值但需要传递值时所使用的占位符值。
     * 目的:该方法用于处理一种特定情况,即当创建者(Creator)方法需要为每个参数传递一个值,但输入中并没有提供值时,我们需要提供一个占位符值。
     * 常见情况:创建者方法通常指的是构造函数、工厂方法或其他用于创建对象实例的方法。这些方法可能要求为所有参数提供值,即使某些值在输入数据中并不存在。
     * 占位符值:占位符值用于替代缺失的输入值。它通常与getNullValue方法返回的值相同(这通常就是Java的null),但对于特定类型,可能需要使用不同的“默认值”。
     * 特定类型:对于某些类型(特别是原始数据类型或不能设置为null的类型),使用null作为占位符值是不合适的。因此,对于这些类型,可能需要重写此方法以提供适当的默认值(例如,对于整数类型,可能是0;对于布尔类型,可能是false等)。
     * 调用频率:该方法每次需要确定占位符值时都会被调用。这意味着,在创建对象实例时,对于每个缺失的输入值,都可能调用此方法。
     * 默认实现:该方法的默认实现是简单地调用getNullValue方法并返回其结果。这意味着,在大多数情况下,占位符值将与null值相同,除非特定类型重写了此方法。
     *
     * @since 2.13
     */
    @Override
    public Object getAbsentValue(DeserializationContext ctxt) throws JsonMappingException {
        return getNullValue(ctxt);
    }

2.4 空值

    /**
     * 空值处理
     */
    public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
        return getNullValue(ctxt);
    }

    /**
     * 检查是否需要仅调用一次(静态值),或者每次需要空值时都调用。
     *
     * @since 2.9
     */
    public AccessPattern getEmptyAccessPattern() {
        return AccessPattern.DYNAMIC;
    }

2.5 其他

    /**
     * 获取处理类型
     *
     * @since 2.3
     */
    public Class<?> handledType() {
        return null;
    }

    /**
     * 获取生成值的逻辑类型
     */
    public LogicalType logicalType() {
        return null;
    }

    /**
     * 检查反序列化器实例是否可缓存,并可用于相同类型(创建实例的类型)的其他属性
     */
    public boolean isCachable() {
        return false;
    }

    /**
     * 获取代理的反序列化器
     *
     * @since 2.1
     */
    public JsonDeserializer<?> getDelegatee() {
        return null;
    }

    /**
     * 获取属性名称,仅用于错误报告和诊断目的
     *
     * @since 2.0
     */
    public Collection<Object> getKnownPropertyNames() {
        return null;
    }


    /**
     * 获取对象标识符值,将其解析为实际的对象实例,并返回为反序列化值。
     * @since 2.0
     */
    public ObjectIdReader getObjectIdReader() {
        return null;
    }

    /**
     * 供 BeanDeserializerFactory 用于处理循环引用问题
     */
    public SettableBeanProperty findBackReference(String refName) {
        throw new IllegalArgumentException("Cannot handle managed/back reference '" + refName
                + "': type: value deserializer of type " + getClass().getName() + " does not support them");
    }

    /**
     * 查看反序列化器是否支持现有值的更新(也称为“合并”)功能(@JavaMerge)
     *
     * @since 2.9
     */
    public Boolean supportsUpdate(DeserializationConfig config) {
        return null;
    }

3. 实现类

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

在这里插入图片描述

3.1 StdDeserializer

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

3.1.1 成员属性

掩码(Bitmask)是一种位操作技术,它允许通过单个整数值来同时设置、检查或清除多个标志位。Jackson允许使用掩码在单个操作中检查多个特性,从而提高性能。

F_MASK_INT_COERCIONS声明的掩码用于于覆盖两个特定的反序列化特性:USE_BIG_INTEGER_FOR_INTSUSE_LONG_FOR_INTS

    protected final static int F_MASK_INT_COERCIONS =
            DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.getMask()
            | DeserializationFeature.USE_LONG_FOR_INTS.getMask();

StdDeserializer还提供了两个成员属性,描述当前处理的值类型和Java对象的类型,便于正确地将JSON数据转换为Java对象:

    // 反序列化器处理的值类型
    final protected Class<?> _valueClass;
    
    // Java对象的类型信息
    final protected JavaType _valueType;
3.1.2 构造

StdDeserializer构造函数则比较简单,主要是对成员属性进行赋值:

    protected StdDeserializer(Class<?> vc) {
        _valueClass = vc;
        _valueType = null;
    }

    protected StdDeserializer(JavaType valueType) {
        // 26-Sep-2017, tatu: [databind#1764] need to add null-check back until 3.x
        _valueClass = (valueType == null) ? Object.class : valueType.getRawClass();
        _valueType = valueType;
    }

    protected StdDeserializer(StdDeserializer<?> src) {
        _valueClass = src._valueClass;
        _valueType = src._valueType;
    }
3.1.3 反序列化

StdDeserializer提供了一个不特定的类型反序列化方法,子类需要处理类型信息时,需要重写该方法:

    @Override
    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
            TypeDeserializer typeDeserializer) throws IOException {
        return typeDeserializer.deserializeTypedFromAny(p, ctxt);
    }

此外还提供了很多特定类型的反序列化方法:

     protected T _deserializeFromArray(JsonParser p, DeserializationContext ctxt)
     protected T _deserializeFromString(JsonParser p, DeserializationContext ctxt)
     protected T _deserializeFromString(JsonParser p, DeserializationContext ctxt)
     protected T _deserializeWrappedValue(JsonParser p, DeserializationContext ctxt) 
     protected final boolean _parseBooleanPrimitive(DeserializationContext ctxt, JsonParser p, Class<?> targetType) 
     protected final Boolean _parseBoolean(JsonParser p, DeserializationContext ctxt, Class<?> targetType)
     protected final short _parseShortPrimitive(JsonParser p, DeserializationContext ctxt)
     protected final int _parseIntPrimitive(JsonParser p, DeserializationContext ctxt)
     protected final int _parseIntPrimitive(DeserializationContext ctxt, String text) 
     protected final int _parseIntPrimitive(DeserializationContext ctxt, String text) 
     protected final Integer _parseInteger(JsonParser p, DeserializationContext ctxt,Class<?> targetType)
     protected final Integer _parseInteger(DeserializationContext ctxt, String text)
     protected final long _parseLongPrimitive(JsonParser p, DeserializationContext ctxt)
     protected final long _parseLongPrimitive(DeserializationContext ctxt, String text) 
     protected final Long _parseLong(JsonParser p, DeserializationContext ctxt, Class<?> targetType)
     protected final Long _parseLong(DeserializationContext ctxt, String text) 
     //......................
3.1.4 辅助方法

检查特殊字符串的相关方法:

    // 字符串值 "null",并且进一步确定是否应将其强制转换为 null
    protected boolean _hasTextualNull(String value) {
        return "null".equals(value);
    }
    protected final boolean _isNegInf(String text) {
        return "-Infinity".equals(text) || "-INF".equals(text);
    }
    protected final boolean _isPosInf(String text) {
        return "Infinity".equals(text) || "INF".equals(text);
    }
    protected final boolean _isNaN(String text) {
        return "NaN".equals(text);
    }

也提供了很多辅助方法,用于校验、查询、判断等,供子类直接调用(太多,这里只列举几个):

    protected Object _coerceIntegral(JsonParser p, DeserializationContext ctxt) throws IOException {
        if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
            return p.getBigIntegerValue();
        } else {
            return ctxt.isEnabled(DeserializationFeature.USE_LONG_FOR_INTS) ? p.getLongValue() : p.getNumberValue();
        }
    }

    protected final void _verifyNullForPrimitive(DeserializationContext ctxt) throws JsonMappingException {
        if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)) {
            ctxt.reportInputMismatch(this, "Cannot coerce `null` to %s (disable `DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES` to allow)", new Object[]{this._coercedTypeDesc()});
        }

    }
3.1.5 实现类

StdDeserializer也包含了多个子实现类,和JsonSerializer类似,只不过是用于反序列化,这里就不再详细解析每个子类了:

在这里插入图片描述

3.2 None

JsonSerializer.None作用一样,是@JsonDeserializer的标记类

3.3 TypeWrappedDeserializer

TypeWrappedSerializer一样,基于包装模式实现。

3.4 AbstractDeserializer

AbstractDeserializer是一个仅用于处理处理反序列化过程中的多态类型的抽象类。

3.5 ErrorThrowingDeserializer

ErrorThrowingDeserializer用于存储在构建反序列化器过程中捕获的 {@link Error},该错误需要被延迟处理,直到实际尝试反序列化给定类型的值时。

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

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

相关文章

基于SpringBoot+Vue的健身器材用品网站(源码+文档+部署+讲解)

一.系统概述 随着我国经济的高速发展与人们生活水平的日益提高&#xff0c;人们对生活质量的追求也多种多样。尤其在人们生活节奏不断加快的当下&#xff0c;人们更趋向于足不出户解决各种问题&#xff0c;必录德健身器材用品网展现了其蓬勃生命力和广阔的前景。与此同时&#…

Redis中的集群(九)

集群 消息 集群中的各个节点通过发送和接收消息(message)来进行通信&#xff0c;我们称发送消息的节点为发送者(sender),接收消息 的节点成为接收者&#xff0c;如图所示。节点发送的消息主要有以下五种: 1.MEET消息:当发送者接到客户端发送的CLUSTER MEET命令时&#xff0c…

# Nacos 服务发现-快速入门-创建服务消费者模块,使用 feign 调用 服务生产者

Nacos 服务发现-快速入门-创建服务消费者模块&#xff0c;使用 feign 调用 服务生产者 1、 新增 quickstart_consumer 子工程&#xff08;子模块&#xff09;&#xff0c; 创建子模块&#xff1a;--> 右键 nacos_discovery 父工程 --> Modules --> Maven --> G…

android gradle版本无法下载

android gradle版本无法下载问题解决方法 在引入一个新的android项目的时候&#xff0c;通常会因为无法下载gradle版本而一直卡在同步界面&#xff0c;类似于下面的情况。 这是因为gradle运行时首先会检查distributionUrlhttps://services.gradle.org/distributions/gradle-5.6…

·13·1dawwd

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

lv_micropython to download and building

想要在ESP32-C3使用Micropython开发GUI&#xff0c;所以需要编译lv_micropython&#xff0c;当前github上的版本是9.1.0。 一、开发环境 因为编译lv_micropython需要在linux系统下&#xff0c;但是我的电脑是windows系统&#xff0c;所以我在windows系统上安装了VMware虚拟机&…

牛客2024【牛客赛文X】春招冲刺ONT61 每日温度【hard 单调栈 Java、Go、PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/1f54e163e6944cc7b8759cc09e9c78d8 思路 单调栈最直接的应用就是获取数组中每个位置i,i的左边第一个比i大或者小的位置/数以及,i的右边第一个比i大或者小的位置/数不懂的同学看这里https://blog.csdn.net/Borsl…

Vulnhub靶机 DC-1渗透详细过程

Vulnhub靶机:DC-1渗透详细过程 目录 Vulnhub靶机:DC-1渗透详细过程一、将靶机导入到虚拟机当中二、攻击方式主机发现端口扫描web渗透利用msf反弹shell数据库信息web管理员密码提权 一、将靶机导入到虚拟机当中 靶机地址&#xff1a; https://www.vulnhub.com/entry/dc-1-1,29…

英伟达高性能芯片供货周期缩短到2-3个月,今年GPU不再紧缺?

戴尔台湾地区总经理Terence Liao近日称&#xff0c;英伟达高性能 AI GPU的交付周期在过去几个月中已从3-4个月缩短到仅2-3个月&#xff0c;进入2024年以来交货等待时间一直在不短缩短&#xff0c;目前的2-3个月已经是英伟达高性能GPU最短的交货期。 英伟达公司正在不断努力提高…

wsl下Linux使用chatglm.cpp记录

目录 前言 一些说明 过程 git chatglm.cpp代码 安装相关包 convert量化ggml cmake构建项目 命令行模型推理 webdemo模型推理 APIServer 性能表现 gpu推理设置 前言 Linux之前用的少&#xff0c;多数还是在Windows下操作&#xff0c;导致对Linux很陌生&#xff0c;…

MES系统中的业务过程管理流程

MES即制造执行系统&#xff0c;也可称为生产执行系统&#xff0c;是一套面向制造企业车间执行层的生产信息化管理系统。 mes系统的业务流程包括哪些方面呢&#xff1a; 一、生产计划与调度 mes系统中的生产计划与调度模块&#xff0c;能够根据企业生产实际情况&#xff0c;制…

淘宝批量采集商品详情数据(属性丨详情图丨sku丨价格等)

淘宝批量采集商品详情数据&#xff08;包括属性、详情图、SKU、价格等&#xff09;可以通过以下几种方式实现&#xff1a; 使用淘宝数据抓取工具&#xff1a;这类工具&#xff0c;如某鱼等&#xff0c;能够自动化采集淘宝商品数据&#xff0c;并将其转换成CSV、Excel等格式&am…

从0到1实现RPC | 12 限流

在服务提供者provider端添加限流逻辑 限流&#xff1a;指定时间内请求数超过指定阈值时就抛出异常。 在ProviderInvoker的调用过程中&#xff0c;添加限流逻辑&#xff1a; 使用滑动窗口SlidingTimeWindow统计30s的请求数&#xff1b;每个服务service对应一个滑动窗口&#…

pom.xml显示灰色并被划线

在使用 IDEA 进行开发的过程中&#xff0c;有时候会遇到 pom.xml 显示灰色并被划线的情况&#xff0c;如下图&#xff1a; 这一般是因为该文件被 Maven 忽略导致的&#xff0c;可以进行如下操作恢复&#xff1a; 设置保存后&#xff0c;可以看到 pom.xml 恢复了正常&#xff1a…

Go语言中如何正确使用 errgroup

不管是哪种编程语言,重新发明轮子都不是一个好主意。代码库重新实现如何启动多个goroutine并汇总错误也很常见。但是Go生态系统中的一个包旨在支持这种常见的用例。让我们来看看这个包并了解为什么它应该成为Go开发人员工具集的一部分。 golang.org/x是一个为标准库提供扩展的…

网络变压器(网络隔离变压器)是如何影响网通设备的传输速率的呢?

Hqst华轩盛(石门盈盛)电子导读&#xff1a;今天介绍网络变压器&#xff08;网络隔离变压器/网络滤波器&#xff09;是如何影响网通设备的传输速率的 一、网络变压器&#xff08;网络隔离变压器/网络滤波器&#xff09;的工作原理 网络变压器&#xff08;网络隔离变压器/网络滤…

04异常Lambda算法正则

异常 异常是什么&#xff1f; 异常是代码在编译或者执行的过程中可能出现的错误。避免异常的出现&#xff0c;同时处理可能出现的异常&#xff0c;让代码更稳健。 异常分为几类&#xff1f; 编译时异常、运行时异常。编译时异常&#xff1a;没有继承RuntimeExcpetion的异常…

python爬虫--------Beautiful Soup 案列(二十一天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

JRT多平台初始化程序

这么多年客户端一直只做Windows&#xff0c;所以初始化程序用C#写个Exe&#xff0c;按网站生成的下载清单文件一个个下载和部署客户端环境是可以的。新的由于设计目标就是支持多平台的&#xff0c;所以需要重新考虑初始化设计。 JRT-Linux初始化演示 JRT-Windows初始化演示 …

【STL详解 —— list的介绍及使用】

STL详解 —— list的介绍及使用 list的介绍list的介绍使用list的构造list iterator的使用list capacitylist element accesslist modifiers 示例list的迭代器失效 list的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭…