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