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.pswp.cn/news/531237.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531237.shtml
英文地址,請注明出處:http://en.pswp.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…

不同包下,相同數據結構的兩個類進行轉換

import com.alibaba.fastjson.JSON; JSON.parseObject(JSON.toJSONString(obj1), obj2.class) import com.fasterxml.jackson.databind.ObjectMapper; objectMapper.convertValue(obj1, obj2.class); 兩個工具類 JsonUtil JacksonHelper 轉載于:https://www.cnblogs.com/hujunz…

git根據用戶過濾提交記錄

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

springboot Autowired BeanNotOfRequiredTypeException

現象 org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named xxxxImpl is expected to be of type com.xxx.xxxImpl but was actually of type com.sun.proxy.$Proxy62 直接Autowired一個實現類&#xff0c;而不是接口 Autowired private XxxServiceI…

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…

TypeReference -- 讓Jackson Json在List/Map中識別自己的Object

private Map<String, Object> buildHeaders(Object params) {ObjectMapper objectMapper JacksonHelper.getMapper();return objectMapper.convertValue(params, new TypeReference<Map<String, Object>>(){}); } 參考How to use Jackson to deserialis…

微信小程序:一起玩連線,一個算法來搞定

微信小程序&#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的相關屬性。 配置…

jackson實現java對象轉支付寶/微信模板消息

一、支付寶消息模板大致長這樣 {"to_user_id": "","telephone": "xxxxx","template": {"template_id": "xxxxxx","context": {"head_color": "#85be53","url"…

簡單封裝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分…

HttpServletRequestWrapper使用技巧(自定義session和緩存InputStream)

一、前言 javax.servlet.http.HttpServletRequestWrapper 是一個開發者可以繼承的類&#xff0c;我們可以重寫相應的方法來實現session的自定義以及緩存InputStream&#xff0c;在程序中可以多次獲取request body的內容。 二、自定義seesion import javax.servlet.http.*;publi…

spring注解工具類AnnotatedElementUtils和AnnotationUtils

一、前言 spring為開發人員提供了兩個搜索注解的工具類&#xff0c;分別是AnnotatedElementUtils和AnnotationUtils。在使用的時候&#xff0c;總是傻傻分不清&#xff0c;什么情況下使用哪一個。于是我做了如下的整理和總結。 二、AnnotationUtils官方解釋 功能 用于處理注解&…