Jackson ObjectMapper readValue过程

 

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)】)

  

  

  

 

转载于:https://www.cnblogs.com/hujunzheng/p/8108488.html

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

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

相关文章

java如何寻找main函数对应的类

参考springboot Class<?> deduceMainApplicationClass() {try {StackTraceElement[] stackTrace new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())…

jooq实践

用法 sql语句 SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, COUNT(*)FROM AUTHORJOIN BOOK ON AUTHOR.ID BOOK.AUTHOR_IDWHERE BOOK.LANGUAGE DEAND BOOK.PUBLISHED > DATE 2008-01-01 GROUP BY AUTHOR.FIRST_NAME, AUTHOR.LAST_NAMEHAVING COUNT(*) > 5 ORDER BY AUT…

git根据用户过滤提交记录

使用SourceTree 使用gitk 转载于:https://www.cnblogs.com/hujunzheng/p/8398203.html

cglib动态代理导致注解丢失问题及如何修改注解允许被继承

现象 SOAService这个bean先后经过两个BeanPostProcessor&#xff0c;会发现代理之后注解就丢失了。 开启了cglib代理 SpringBootApplication EnableAspectJAutoProxy(proxyTargetClass true) public class Application {public static void main(String[] args) {SpringApplic…

spring AbstractBeanDefinition创建bean类型是动态代理类的方式

1.接口 Class<?> resourceClass 2.获取builder BeanDefinitionBuilder builder BeanDefinitionBuilder.genericBeanDefinition(resourceClass); 3.获取接口对应的动态代理class Class<?> targetProxyClass Proxy.getProxyClass(XXX.class.getClassLoader(), ne…

微信小程序:一起玩连线,一个算法来搞定

微信小程序&#xff1a;一起玩连线 游戏玩法 将相同颜色的结点连接在一起&#xff0c;连线之间不能交叉。 算法思想 转换为多个源点到达对应终点的路径问题&#xff0c;且路径之间不相交。按照dfs方式寻找两个结点路径&#xff0c;一条路径探索完之后&#xff0c;标记地图并记录…

IntelliJ IDEA关于logger的live template配置

1.安装 log support2插件 2.配置log support2 由于项目中的日志框架是公司自己封装的&#xff0c;所以还需要自己手动改一下 log support2插件生成的live template 当然也可以修改 Log support global的配置 包括 Logger Field、Logger class、Logger Factory class都可以修改。…

springboot项目接入配置中心,实现@ConfigurationProperties的bean属性刷新方案

前言 配置中心&#xff0c;通过keyvalue的形式存储环境变量。配置中心的属性做了修改&#xff0c;项目中可以通过配置中心的依赖&#xff08;sdk&#xff09;立即感知到。需要做的就是如何在属性发生变化时&#xff0c;改变带有ConfigurationProperties的bean的相关属性。 配置…

简单封装kafka相关的api

一、针对于kafka版本 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>0.8.2.2</version></dependency><dependency><groupId>org.apache.kafka</groupId>…

springmvc controller动态设置content-type

springmvc RequestMappingHandlerAdapter#invokeHandlerMethod 通过ServletInvocableHandlerMethod#invokeAndHandle调用目标方法&#xff0c;并处理返回值。 如果return value &#xff01; null&#xff0c;则通过returnvalueHandlers处理&#xff0c;内部会调用MessageConv…

springboot2.0 redis EnableCaching的配置和使用

一、前言 关于EnableCaching最简单使用&#xff0c;个人感觉只需提供一个CacheManager的一个实例就好了。springboot为我们提供了cache相关的自动配置。引入cache模块&#xff0c;如下。 二、maven依赖 <dependency><groupId>org.springframework.boot</groupId…

依赖配置中心实现注有@ConfigurationProperties的bean相关属性刷新

配置中心是什么 配置中心&#xff0c;通过keyvalue的形式存储环境变量。配置中心的属性做了修改&#xff0c;项目中可以通过配置中心的依赖&#xff08;sdk&#xff09;立即感知到。需要做的就是如何在属性发生变化时&#xff0c;改变带有ConfigurationProperties的bean的相关属…

java接口签名(Signature)实现方案

预祝大家国庆节快乐&#xff0c;赶快迎接美丽而快乐的假期吧&#xff01;&#xff01;&#xff01; 前言 在为第三方系统提供接口的时候&#xff0c;肯定要考虑接口数据的安全问题&#xff0c;比如数据是否被篡改&#xff0c;数据是否已经过时&#xff0c;数据是否可以重复提交…

Git rebase命令实战

一、前言 一句话&#xff0c;git rebase 可以帮助项目中的提交历史干净整洁&#xff01;&#xff01;&#xff01; 二、避免合并出现分叉现象 git merge操作 1、新建一个 develop 分支 2、在develop分支上新建两个文件 3、然后分别执行 add、commit、push 4、接着切换到master分…

windows系统nexus3安装和配置

一、前言 为什么要在本地开发机器上安装nexus&#xff1f;首先声明公司内部是有自己的nexus仓库&#xff0c;但是对上传jar包做了限制&#xff0c;不能畅快的上传自己测试包依赖。于是就自己在本地搭建了一个nexus私服&#xff0c;即可以使用公司nexus私服仓库中的依赖&#xf…

Springmvc借助SimpleUrlHandlerMapping实现接口开关功能

一、接口开关功能 1、可配置化&#xff0c;依赖配置中心 2、接口访问权限可控 3、springmvc不会扫描到&#xff0c;即不会直接的将接口暴露出去 二、接口开关使用场景 和业务没什么关系&#xff0c;主要方便查询系统中的一些状态信息。比如系统的配置信息&#xff0c;中间件的状…

log4j平稳升级到log4j2

一、前言 公司中的项目虽然已经用了很多的新技术了&#xff0c;但是日志的底层框架还是log4j&#xff0c;个人还是不喜欢用这个的。最近项目再生产环境上由于log4j引起了一场血案&#xff0c;于是决定升级到log4j2。 二、现象 虽然生产环境有多个结点分散高并发带来的压力&…

Springboot集成ES启动报错

报错内容 None of the configured nodes are available elasticsearch.yml配置 cluster.name: ftest node.name: node-72 node.master: true node.data: true network.host: 112.122.245.212 http.port: 39200 transport.tcp.port: 39300 discovery.zen.ping.unicast.hosts: [&…

kafka-manager配置和使用

kafka-manager配置 最主要配置就是用于kafka管理器状态的zookeeper主机。这可以在conf目录中的application.conf文件中找到。 kafka-manager.zkhosts"my.zookeeper.host.com:2181" 当然也可以声明为zookeeper集群。 kafka-manager.zkhosts"my.zookeeper.host.co…

kafka告警简单方案

一、前言 为什么要设计kafka告警方案&#xff1f;现成的监控项目百度一下一大堆&#xff0c;KafkaOffsetMonitor、KafkaManager、 Burrow等&#xff0c;具体参考&#xff1a;kafka的消息挤压监控。由于本小组的项目使用的kafka集群并没有被公司的kafka-manager管理&#xff0c;…