Jackson ObjectMapper readValue过程

简介: 1.整体调用栈 2.看一下调用栈的两个方法             resolve 方法中通过 Iterator i$ = this._beanProperties.iterator() 遍历属性的所有子属性,缓存对应的 deserializer。

 

1.整体调用栈

2.看一下调用栈的两个方法

   

  

  

  resolve 方法中通过 Iterator i$ = this._beanProperties.iterator() 遍历属性的所有子属性,缓存对应的 deserializer。观察调用栈的方法,可以发现是循环调用的。

 

3.比如寻找自定义的 LocalDateTime类的序列化实现类,看方法调用栈最上边的方法

  

 

  如果没有找到用户自定义的反序列化工具,则去找默认的标准反序列化工具

  

  

  

  deser = NumberDeserializers.find(rawType, clsName);
deser = DateDeserializers.find(rawType, clsName); 

  可以看一下 com.fasterxml.jackson.databind.deser.std.DateDeserializers 和 com.fasterxml.jackson.databind.deser.std.NumberDeserializers,遍豁然开朗。

4.加入对应类型序列化工具类

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import xxx.utils.json.deserializers.LocalDateDeserializer;
import xxx.utils.json.deserializers.LocalDateTimeDeserializer;
import xxx.utils.json.deserializers.LocalTimeDeserializer;
import xxx.utils.json.serializers.BigDecimalSerializer;
import xxx.utils.json.serializers.LocalDateSerializer;
import xxx.utils.json.serializers.LocalDateTimeSerializer;
import xxx.utils.json.serializers.LocalTimeSerializer;

public class JacksonHelper {
    private static final SimpleModule module = initModule();
    private static final ObjectMapper mapper;
    private static final ObjectMapper prettyMapper;

    public JacksonHelper() {
    }

    private static SimpleModule initModule() {
        return (new SimpleModule()).addSerializer(BigDecimal.class, new BigDecimalSerializer()).addSerializer(LocalTime.class, new LocalTimeSerializer()).addDeserializer(LocalTime.class, new LocalTimeDeserializer()).addSerializer(LocalDate.class, new LocalDateSerializer()).addDeserializer(LocalDate.class, new LocalDateDeserializer()).addSerializer(LocalDateTime.class, new LocalDateTimeSerializer()).addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
    }

    public static JavaType genJavaType(Type type) {
        return getMapper().getTypeFactory().constructType(type);
    }

    public static ObjectMapper getMapper() {
        return mapper;
    }

    public static ObjectMapper getPrettyMapper() {
        return prettyMapper;
    }

    static {
        mapper = (new ObjectMapper()).registerModule(module).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true).configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        prettyMapper = mapper.copy().configure(SerializationFeature.INDENT_OUTPUT, true);
    }
}
MAPPER = JacksonHelper.getMapper().registerModule((new SimpleModule(LocalDateTimeDeserializer2.class.getName())).addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer2()));
        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);

 

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
    public LocalDateTimeDeserializer() {
    }

    public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        String dateTimeStr = ((JsonNode)jp.getCodec().readTree(jp)).asText();
        return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }
}
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeDeserializer2 extends JsonDeserializer<LocalDateTime> {
    public LocalDateTimeDeserializer2() {
    }

    public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        String dateTimeStr = ((JsonNode)jp.getCodec().readTree(jp)).asText();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return LocalDateTime.parse(dateTimeStr, df);
    }
}

 

  可见,ObjectMapper registerModule 最后注册的module会优先被发现。例如上边首先 第一个 Module加入了一个LocalDateTime反序列化工具类LocalDateTimeDeserializer,接着第二个Module加入了LocalDateTime反序列化工具类LocalDateTimeDeserializer2,最后得到的反序列化工具类是LocalDateTimeDeserializer2。

5.java.util.Date日期类型解析

  日期格式:yyyy-MM-dd HH:mm:ss

  第一种方法:MAPPER.setConfig(MAPPER.getDeserializationConfig().with(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));

  第二种方法:自定义反序列化 MAPPER.registerModule((new SimpleModule(Date.class.getName())).addDeserializer(Date.class, DateDeserializer2.dateDeserializer));

import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class DateDeserializer2 extends DateDeserializers.DateDeserializer{
    public static final DateDeserializer2 dateDeserializer = new DateDeserializer2(
            DateDeserializers.DateDeserializer.instance
            , new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss");

    public DateDeserializer2() {}

    public DateDeserializer2(DateDeserializers.DateDeserializer base, DateFormat df, String formatString) {
        super(base, df, formatString);
    }
}

 

  默认的Date解析通过 DateDeserializers.DateDeserializer,时间的格式化处理是调用自己的StdDateFormat类来实现日期格式化

  

  而StdDateFormat定义的格式化如下

  

   

  DeserializationContext中为啥可以获取StdDateFormat(objectMapper readValue 时会创建DeserializationContext, 注入DeserializationConfig【包含BaseSettings(包含DateFormat)】)

  

  

 

  

 

目录
相关文章
|
计算机视觉
OpenCV3 和 Qt5 计算机视觉:1~5
OpenCV3 和 Qt5 计算机视觉:1~5
403 0
|
机器学习/深度学习 人工智能 测试技术
【自定义插件系列】0基础在阿里云百炼上玩转大模型自定义插件
本文介绍了如何在阿里云百炼平台上创建大模型自定义插件,以增强AI模型功能或适配特定需求。通过编程接口(API)或框架设计外部扩展模块,开发者可在不修改底层参数的情况下扩展模型能力。文章以万相文生图V2版模型为例,详细说明了创建自定义插件的五个步骤:新建插件、创建工具、测试工具、复制第二个工具及最终测试发布。同时,提供了官方文档参考链接和具体参数设置指导,帮助用户轻松实现插件开发与应用,推动AI技术在各行业的广泛应用。
1745 0
「Mac畅玩鸿蒙与硬件15」鸿蒙UI组件篇5 - Slider和Progress组件
Slider 和 Progress 是鸿蒙系统中的常用 UI 组件。Slider 控制数值输入,如音量调节;Progress 显示任务的完成状态,如下载进度。本文通过代码示例展示如何使用这些组件,并涵盖 进度条类型介绍、节流优化、状态同步 和 定时器动态更新。
335 7
「Mac畅玩鸿蒙与硬件15」鸿蒙UI组件篇5 - Slider和Progress组件
|
缓存 JavaScript 开发者
网页离线缓存 Service Worke
网页离线缓存 Service Worke
540 4
|
Java 开发工具 Android开发
Android经典面试题之开发中常见的内存泄漏,以及如何避免和防范
本文介绍Android开发中内存泄漏的概念及其危害,并列举了四种常见泄漏原因:静态变量持有Context、非静态内部类、资源未释放及监听器未注销。提供了具体代码示例和防范措施,如使用ApplicationContext、弱引用、适时释放资源及利用工具检测泄漏。通过遵循这些建议,开发者可以有效提高应用稳定性和性能。
199 0
|
机器学习/深度学习 分布式计算 数据处理
在Python中应用Spark框架
在Python中应用Spark框架
282 1
|
数据安全/隐私保护
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Line Edit的使用及说明
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Line Edit的使用及说明
1920 0
|
存储 分布式计算 Hadoop
ClickHouse(01)什么是ClickHouse,ClickHouse适用于什么场景
ClickHouse是一款高性能的列式存储OLAP数据库,由俄罗斯的Yandex公司开发,用于在线分析处理(OLAP)。它提供秒级大数据查询,适用于商业智能、广告流量等领域。ClickHouse速度快的原因包括列式存储、数据压缩、向量化执行和多线程分布式处理。然而,它不支持事务,不适合OLTP操作。相比Hadoop生态中的查询引擎,ClickHouse在大量数据查询上表现出色。一系列的文章详细介绍了ClickHouse的各个方面,包括安装、表引擎和使用场景。
2332 2
ClickHouse(01)什么是ClickHouse,ClickHouse适用于什么场景
uniapp 制作 wgt 包(用于 app 的热更新)
uniapp 制作 wgt 包(用于 app 的热更新)
1801 0
|
监控 安全 算法
提升编程效率的利器: 解析Google Guava库之RateLimiter优雅限流(十)
提升编程效率的利器: 解析Google Guava库之RateLimiter优雅限流(十)