Springboot2以代碼的方式統(tǒng)一配置Jackson教程
說明
本文主要配置Jackson對(duì)Long、Date、LocalDate、LocalDateTime的序列化和反序列化。
由于js中整數(shù)可精確表示范圍小于java Long的范圍,故將Long序列化為String,反序列化Jackson會(huì)自動(dòng)處理String轉(zhuǎn)Long,故不需要顯式配置。
由于時(shí)間戳在各語(yǔ)言間的兼容性良好,故將Date、LocalDate、LocalDateTime序列化為L(zhǎng)ong(目前時(shí)間戳類的Long類型在js的可精確表示范圍內(nèi)),將Long反序列化為Date、LocalDate、LocalDateTime。將String空字符串反序列化為null。
本文除了配置Springboot整合的Jackson,還配置了功能一致的Jackson工具類,方便在代碼中顯示使用Jackson的序列化和反序列化功能。
7個(gè)序列化和反序列化規(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)的時(shí)間戳格式
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// 設(shè)置為中國(guó)北京時(shí)區(qū)
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
// 空值不序列化
// objectMapper.setSerializationInclusion(Include.NON_NULL);//已過時(shí)
// objectMapper.setDefaultPropertyInclusion(Include.NON_NULL);//新API
// 反序列化時(shí),屬性不存在的兼容處理
objectMapper.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 單引號(hào)處理
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錯(cuò)誤");
}
}
@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錯(cuò)誤", 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錯(cuò)誤");
}
}
/**
* obj對(duì)象 轉(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錯(cuò)誤");
}
}
/**
* 解碼json串成對(duì)象
*
* @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é)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring MVC接口防數(shù)據(jù)篡改和重復(fù)提交
這篇文章主要為大家詳細(xì)介紹了Spring MVC接口防數(shù)據(jù)篡改和重復(fù)提交,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08
SPRINGBOOT讀取PROPERTIES配置文件數(shù)據(jù)過程詳解
這篇文章主要介紹了SPRINGBOOT讀取PROPERTIES配置文件數(shù)據(jù)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
java實(shí)現(xiàn)微信小程序加密數(shù)據(jù)解密算法
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)微信小程序加密數(shù)據(jù)解密算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09
java如何使用zip壓縮實(shí)現(xiàn)讀取寫入
這篇文章主要為大家介紹了java如何使用zip壓縮實(shí)現(xiàn)讀取寫入示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
基于Java實(shí)現(xiàn)無向環(huán)和有向環(huán)的檢測(cè)
這篇文章主要介紹了如何在?Java?中實(shí)現(xiàn)無向環(huán)和有向環(huán)的檢測(cè),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下2022-04-04
SpringBoot集成ElasticSearch的示例代碼
Elasticsearch是用Java語(yǔ)言開發(fā)的,并作為Apache許可條款下的開放源碼發(fā)布,是一種流行的企業(yè)級(jí)搜索引擎,本文給大家介紹SpringBoot集成ElasticSearch的示例代碼,感興趣的朋友一起看看吧2022-02-02
Springboot初始化啟動(dòng)報(bào)錯(cuò)Error?creating?bean?with?name?'da
這篇文章主要為大家介紹了Springboot初始化啟動(dòng)報(bào)Error?creating?bean?with?name?'dataSource'?defined?in?class?path?resource解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08

