Springboot2以代碼的方式統(tǒng)一配置Jackson教程
說明
本文主要配置Jackson對Long、Date、LocalDate、LocalDateTime的序列化和反序列化。
由于js中整數(shù)可精確表示范圍小于java Long的范圍,故將Long序列化為String,反序列化Jackson會自動處理String轉(zhuǎn)Long,故不需要顯式配置。
由于時間戳在各語言間的兼容性良好,故將Date、LocalDate、LocalDateTime序列化為Long(目前時間戳類的Long類型在js的可精確表示范圍內(nèi)),將Long反序列化為Date、LocalDate、LocalDateTime。將String空字符串反序列化為null。
本文除了配置Springboot整合的Jackson,還配置了功能一致的Jackson工具類,方便在代碼中顯示使用Jackson的序列化和反序列化功能。
7個序列化和反序列化規(guī)則
package com.xxx.config.serializers; import java.io.IOException; import java.util.Date; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; public class DateSerializer extends JsonSerializer<Date> { @Override public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value != null) { gen.writeNumber(value.getTime()); } } }
package com.xxx.config.serializers; import java.io.IOException; import java.time.LocalDate; import java.time.ZoneId; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; public class LocalDateSerializer extends JsonSerializer<LocalDate> { @Override public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value != null) { long millis = value.atStartOfDay(ZoneId.of("+8")).toInstant().toEpochMilli(); gen.writeNumber(millis); } } }
package com.xxx.config.serializers; import java.io.IOException; import java.time.LocalDateTime; import java.time.ZoneId; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> { @Override public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value != null) { long millis = value.atZone(ZoneId.of("+8")).toInstant().toEpochMilli(); gen.writeNumber(millis); } } }
package com.xxx.config.serializers; import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; public class StringDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { String text = p.getText(); if ("".equals(text)) { return null; } return text; } }
package com.xxx.config.serializers; import java.io.IOException; import java.util.Date; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; public class DateDeserializer extends JsonDeserializer<Date> { @Override public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { long timestamp = p.getValueAsLong(); if (timestamp > 0){ return new Date(timestamp); }else{ return null; } } }
package com.xxx.config.serializers; import java.io.IOException; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; public class LocalDateDeserializer extends JsonDeserializer<LocalDate> { @Override public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { long timestamp = p.getValueAsLong(); if (timestamp > 0){ return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp),ZoneId.of("+8")).toLocalDate(); }else{ return null; } } }
package com.xxx.config.serializers; import java.io.IOException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { @Override public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { long timestamp = p.getValueAsLong(); if (timestamp > 0){ return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp),ZoneId.of("+8")); }else{ return null; } } }
Jackson統(tǒng)一配置類
package com.xxx.config; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Date; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import com.xxx.config.serializers.DateDeserializer; import com.xxx.config.serializers.DateSerializer; import com.xxx.config.serializers.LocalDateDeserializer; import com.xxx.config.serializers.LocalDateSerializer; import com.xxx.config.serializers.LocalDateTimeDeserializer; import com.xxx.config.serializers.LocalDateTimeSerializer; import com.xxx.config.serializers.StringDeserializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; @Configuration public class JacksonConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { Jackson2ObjectMapperBuilderCustomizer customizer = new Jackson2ObjectMapperBuilderCustomizer() { @Override public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { jacksonObjectMapperBuilder .serializerByType(Long.TYPE, ToStringSerializer.instance) .serializerByType(Long.class, ToStringSerializer.instance) .serializerByType(Date.class, new DateSerializer()) .serializerByType(LocalDate.class, new LocalDateSerializer()) .serializerByType(LocalDateTime.class, new LocalDateTimeSerializer()) .deserializerByType(String.class, new StringDeserializer()) .deserializerByType(Date.class, new DateDeserializer()) .deserializerByType(LocalDate.class, new LocalDateDeserializer()) .deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer()) .failOnEmptyBeans(false) .failOnUnknownProperties(false); } }; return customizer; } }
Jackson工具類
package com.xxx.util; import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Date; import java.util.TimeZone; import com.xxx.config.serializers.StringDeserializer; import com.xxx.config.serializers.DateDeserializer; import com.xxx.config.serializers.DateSerializer; import com.xxx.config.serializers.LocalDateDeserializer; import com.xxx.config.serializers.LocalDateSerializer; import com.xxx.config.serializers.LocalDateTimeDeserializer; import com.xxx.config.serializers.LocalDateTimeSerializer; import com.fasterxml.jackson.core.JsonParser.Feature; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; public class JsonUtils { private static final ObjectMapper objectMapper; static { objectMapper = new ObjectMapper(); // 去掉默認(rèn)的時間戳格式 objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // 設(shè)置為中國北京時區(qū) objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8")); // 空值不序列化 // objectMapper.setSerializationInclusion(Include.NON_NULL);//已過時 // objectMapper.setDefaultPropertyInclusion(Include.NON_NULL);//新API // 反序列化時,屬性不存在的兼容處理 objectMapper.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 單引號處理 objectMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true); JavaTimeModule javaTimeModule = new JavaTimeModule(); javaTimeModule.addSerializer(Long.TYPE, ToStringSerializer.instance); javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance); javaTimeModule.addSerializer(Date.class, new DateSerializer()); javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer()); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer()); javaTimeModule.addDeserializer(String.class, new StringDeserializer()); javaTimeModule.addDeserializer(Date.class, new DateDeserializer()); javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer()); javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer()); objectMapper.registerModule(javaTimeModule); } /** * json 轉(zhuǎn)換成 Object * * @param json * @param clazz * @return */ public static <T> T json2Object(String json, Class<T> clazz) { try { return objectMapper.readValue(json, clazz); } catch (IOException e) { throw new RuntimeException("解析json錯誤"); } } @SuppressWarnings("unchecked") public static <T> T json2Object(String json, TypeReference<T> tr) { try { return (T)objectMapper.readValue(json, tr); } catch (IOException e) { throw new RuntimeException("解析json錯誤", e); } } /** * obj 轉(zhuǎn)換成json * * @param entity * @return */ public static <T> String object2Json(T entity) { try { return objectMapper.writeValueAsString(entity); } catch (IOException e) { throw new RuntimeException("轉(zhuǎn)換json錯誤"); } } /** * obj對象 轉(zhuǎn)換成樹型JSON * * @param obj * @return */ public static JsonNode object2TreeJson(Object obj) { try { return objectMapper.valueToTree(obj); } catch (Exception e) { throw new RuntimeException("轉(zhuǎn)換json錯誤"); } } /** * 解碼json串成對象 * * @param <T> * @param json * @param valueType * @return T */ @SuppressWarnings("unchecked") public static <T> T decode(String json, Class<?> valueType) { try { return (T) objectMapper.readValue(json, valueType); } catch (Exception e) { throw new RuntimeException(json, e); } } /** * 解碼json串成JsonNode * @param json * @return */ public static JsonNode readTree(String json) { try { return objectMapper.readTree(json); } catch (Exception e) { throw new RuntimeException(json, e); } } }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring MVC接口防數(shù)據(jù)篡改和重復(fù)提交
這篇文章主要為大家詳細(xì)介紹了Spring MVC接口防數(shù)據(jù)篡改和重復(fù)提交,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-08-08SPRINGBOOT讀取PROPERTIES配置文件數(shù)據(jù)過程詳解
這篇文章主要介紹了SPRINGBOOT讀取PROPERTIES配置文件數(shù)據(jù)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12java實現(xiàn)微信小程序加密數(shù)據(jù)解密算法
這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)微信小程序加密數(shù)據(jù)解密算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09基于Java實現(xiàn)無向環(huán)和有向環(huán)的檢測
這篇文章主要介紹了如何在?Java?中實現(xiàn)無向環(huán)和有向環(huán)的檢測,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下2022-04-04SpringBoot集成ElasticSearch的示例代碼
Elasticsearch是用Java語言開發(fā)的,并作為Apache許可條款下的開放源碼發(fā)布,是一種流行的企業(yè)級搜索引擎,本文給大家介紹SpringBoot集成ElasticSearch的示例代碼,感興趣的朋友一起看看吧2022-02-02Springboot初始化啟動報錯Error?creating?bean?with?name?'da
這篇文章主要為大家介紹了Springboot初始化啟動報Error?creating?bean?with?name?'dataSource'?defined?in?class?path?resource解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08