SpringBoot之Json的序列化和反序列化問(wèn)題
控制json序列化/反序列化
1. @JsonIgnoreProperties的用法
@JsonIgnoreProperties(value = { "prop1","prop2" })用來(lái)修飾Pojo類(lèi), 在序列化和反序列化的時(shí)候忽略指定的屬性, 可以忽略一個(gè)或多個(gè)屬性.
@JsonIgnoreProperties(ignoreUnknown = true)
用來(lái)修飾Pojo類(lèi), 在反序列化的時(shí)候忽略那些無(wú)法被設(shè)置的屬性, 包括無(wú)法在構(gòu)造子設(shè)置和沒(méi)有對(duì)應(yīng)的setter方法.
2. @JsonProperty 注解
如果 json field 的名稱(chēng)和Pojo 的屬性名不一致的時(shí), 可以用 @JsonProperty 來(lái)注解 getter() 或 setter() 方法, 該注解設(shè)定json 對(duì)應(yīng)的屬性名, 另外@JsonProperty也經(jīng)常用來(lái)注解構(gòu)造子的形參, 這時(shí)候構(gòu)造子應(yīng)該加@JsonCreator 注解.
3. @JsonCreator 注解
如果 Pojo 類(lèi)定義有參數(shù)的構(gòu)造子, 但沒(méi)有提供無(wú)參構(gòu)造子時(shí), 在反序列化時(shí)是會(huì)報(bào)錯(cuò). 有下面兩個(gè)辦法:
- 方法1:增加一個(gè)無(wú)參構(gòu)造子
- 方法2:為這個(gè)有參數(shù)的構(gòu)造子, 加上 @JsonCreator 注解, 同時(shí)參數(shù)需要加上 @JsonProperty 注解.
4. @JsonSetter 和 @JsonGetter 注解
如果 json field 的名稱(chēng)和Pojo 的屬性名不一致的時(shí), 可以使用@JsonGetter來(lái)注解 getter(), 使用 @JsonSetter 來(lái)注解setter() 方法. 這兩個(gè)注解都可以指定一個(gè)屬性名. 這兩個(gè)注解都可以用 @JsonProperty 替換.
5. @JsonAnySetter 注解
一般對(duì)象屬性名都是確定的, 比如 Car 這個(gè)對(duì)象, 有 brand/price 等具名屬性, 但有時(shí)候我們還需要為Car這個(gè)對(duì)象設(shè)定一些擴(kuò)展屬性, 這些擴(kuò)展屬性名稱(chēng)暫時(shí)不好確定, 通常使用 Map<String, String> 來(lái)存放這些擴(kuò)展屬性的K/V. 要把json 數(shù)據(jù)中的這些屬性反序列化到類(lèi)的Map中, 需要在類(lèi)上增加一個(gè)K/V的setter方法, 而且這個(gè)setter方法要加上@JsonAnySetter注解.
public class Car {
public String brand;
private Map<String, String> properties;
@JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
}一旦類(lèi)加上了@JsonAnySetter后可將下面的 json 數(shù)據(jù)反序列化到Map中:
{
"brand":"Benz",
"attr2":"val2",
"attr1":"val1"
}6. @JsonAnyGetter 注解
和@JsonAnySetter 注解相對(duì)應(yīng), 如果要將類(lèi)中的Map K/V屬性序列化到j(luò)son中, 需要在類(lèi)上增加一個(gè) @JsonAnyGetter 方法, 該方法直接返回KV map就行.
public class Car {
? ? public String brand;
? ? private Map<String, String> properties;
?
? ? @JsonAnyGetter
? ? public Map<String, String> getProperties() {
? ? ? ? return properties;
? ? }
}序列化后的json為:
{
"brand":"Benz",
"attr2":"val2",
"attr1":"val1"
}7. @JsonFormat 注解
通常明確Date/Time 屬性序列化用的時(shí)間格式.
public class Event {
? ? public String name;
?
? ? @JsonFormat(
? ? ? shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
? ? public Date eventDate;
}8.@JsonSerialize 和 @JsonDeserialize 注解
@JsonSerialize注解可以為類(lèi)屬性設(shè)定專(zhuān)門(mén)的序列化函數(shù), @JsonDeserialize注解用來(lái)為json屬性定制化反序列化函數(shù)
SpringBoot序列化規(guī)則
Include.Include.ALWAYS默認(rèn)Include.NON_DEFAULT屬性為默認(rèn)值不序列化Include.NON_EMPTY屬性為 空(“”) 或者為 NULL 都不序列化Include.NON_NULL屬性為NULL 不序列化
1.全局設(shè)置
/**
* 〈返回json空值去掉null和""〉 〈功能詳細(xì)描述〉
*
* @author gogym
* @version 2017年10月13日
* @see JacksonConfig
* @since
*/
@Configuration
public class JacksonConfig
{
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
{
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// 通過(guò)該方法對(duì)mapper對(duì)象進(jìn)行設(shè)置,所有序列化的對(duì)象都將按改規(guī)則進(jìn)行系列化
// Include.Include.ALWAYS 默認(rèn)
// Include.NON_DEFAULT 屬性為默認(rèn)值不序列化
// Include.NON_EMPTY 屬性為 空("") 或者為 NULL 都不序列化,則返回的json是沒(méi)有這個(gè)字段的。這樣對(duì)移動(dòng)端會(huì)更省流量
// Include.NON_NULL 屬性為NULL 不序列化,就是為null的字段不參加序列化
//objectMapper.setSerializationInclusion(Include.NON_EMPTY);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
return objectMapper;
}
}或者
spring.jackson.default-property-inclusion=non_null
spring:
jackson:
default-property-inclusion: non_null2.局部設(shè)置
在需要設(shè)置的實(shí)體類(lèi)或者字段上加上注解
@JsonInclude(Include.NON_NULL)
3.自定義局部序列化
(1)、自定義一個(gè)序列化工具類(lèi),需要實(shí)現(xiàn)StdSerializer<T>或者JsonSerializer<T>
public class ClientObjectSerialize extends JsonSerializer<CreditBorrowerRepaymentRequestDto>{
@Override
public void serialize(CreditBorrowerRepaymentRequestDto dto, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeStartObject();
try {
Field[] fields = dto.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if(null == field.get(dto)){
continue;
}
jsonGenerator.writeFieldName(field.getName());
jsonGenerator.writeObject(field.get(dto));
}
} catch (Exception e) {
e.printStackTrace();
}
jsonGenerator.writeEndObject();
}
}(2)使用注解作用在實(shí)體類(lèi)上
@JsonSerialize(using = ClientObjectSerialize.class)
public class CreditBorrowerRepaymentRequestDto{
}(3)可以作用在實(shí)體對(duì)象字段上,對(duì)NULL值的處理,或者轉(zhuǎn)換
@JsonSerialize(using = ClientStringSerialize.class)
private String name;
@JsonSerialize(using = ClientDtaeSerialize.class)
private Date date;
public class ClientStringSerialize extends JsonSerializer<String> {
@Override
public void serialize(String string, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if(string == null){
jsonGenerator.writeString(string + "[NULL]");
}else{
jsonGenerator.writeString(string);
}
}
}
public class ClientDtaeSerialize extends JsonSerializer<Date> {
@Override
public void serialize(Date createDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createDate));
}
}4.自定義全局 null 轉(zhuǎn)換 序列化
SpringBoot返回Json數(shù)據(jù)中null值處理,將字符串類(lèi)型null值轉(zhuǎn)換為"",將集合數(shù)組類(lèi)型null值轉(zhuǎn)換為[],將原始數(shù)據(jù)類(lèi)型null值轉(zhuǎn)換為0,將布爾類(lèi)型null值轉(zhuǎn)換為false,將實(shí)體對(duì)象null值轉(zhuǎn)換為{}。
(1)自定義null值序列化處理器
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
/**
* 自定義null值序列化處理器
*/
public class CustomizeNullJsonSerializer {
/**
* 處理數(shù)組集合類(lèi)型的null值
*/
public static class NullArrayJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object value, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartArray();
jsonGenerator.writeEndArray();
}
}
/**
* 處理字符串類(lèi)型的null值
*/
public static class NullStringJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object value, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString("");
}
}
/**
* 處理數(shù)值類(lèi)型的null值
*/
public static class NullNumberJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object value, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeNumber(0);
}
}
/**
* 處理boolean類(lèi)型的null值
*/
public static class NullBooleanJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object value, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeBoolean(false);
}
}
/**
* 處理實(shí)體對(duì)象類(lèi)型的null值
*/
public static class NullObjectJsonSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object value, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeEndObject();
}
}
}(2)序列化程序修改器
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.util.Collection;
import java.util.List;
/**
* <pre>
* 此modifier主要做的事情為:
* 1.當(dāng)序列化類(lèi)型為數(shù)組集合時(shí),當(dāng)值為null時(shí),序列化成[]
* 2.String類(lèi)型值序列化為""
*
* </pre>
*/
public class MyBeanSerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
BeanDescription beanDesc,
List<BeanPropertyWriter> beanProperties) {
// 循環(huán)所有的beanPropertyWriter
for (int i = 0; i < beanProperties.size(); i++) {
BeanPropertyWriter writer = beanProperties.get(i);
// 判斷字段的類(lèi)型,如果是數(shù)組或集合則注冊(cè)nullSerializer
if (isArrayType(writer)) {
// 給writer注冊(cè)一個(gè)自己的nullSerializer
writer.assignNullSerializer(new CustomizeNullJsonSerializer.NullArrayJsonSerializer());
}
if (isStringType(writer)) {
writer.assignNullSerializer(new CustomizeNullJsonSerializer.NullStringJsonSerializer());
}
}
return beanProperties;
}
/**
* 是否是數(shù)組
*/
private boolean isArrayType(BeanPropertyWriter writer) {
Class<?> clazz = writer.getType().getRawClass();
return clazz.isArray() || Collection.class.isAssignableFrom(clazz);
}
/**
* 是否是String
*/
private boolean isStringType(BeanPropertyWriter writer) {
Class<?> clazz = writer.getType().getRawClass();
return CharSequence.class.isAssignableFrom(clazz) || Character.class.isAssignableFrom(clazz);
}
/**
* 是否是數(shù)值類(lèi)型
*/
private boolean isNumberType(BeanPropertyWriter writer) {
Class<?> clazz = writer.getType().getRawClass();
return Number.class.isAssignableFrom(clazz);
}
/**
* 是否是boolean
*/
private boolean isBooleanType(BeanPropertyWriter writer) {
Class<?> clazz = writer.getType().getRawClass();
return clazz.equals(Boolean.class);
}
}(3)配置Jackson實(shí)體
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
/**
* 配置Jackson實(shí)體
*/
@Configuration
public class JacksonConfig {
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
/** 為objectMapper注冊(cè)一個(gè)帶有SerializerModifier的Factory */
objectMapper.setSerializerFactory(objectMapper.getSerializerFactory()
.withSerializerModifier(new MyBeanSerializerModifier()));
SerializerProvider serializerProvider = objectMapper.getSerializerProvider();
serializerProvider.setNullValueSerializer(new CustomizeNullJsonSerializer
.NullObjectJsonSerializer());
return objectMapper;
}
}以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java的Struts框架中登陸功能的實(shí)現(xiàn)和表單處理器的使用
這篇文章主要介紹了Java的Struts框架中登陸功能的實(shí)現(xiàn)和表單處理器的使用,Struts框架是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下2015-12-12
java shiro實(shí)現(xiàn)退出登陸清空緩存
本篇文章主要介紹了java shiro實(shí)現(xiàn)退出登陸清空緩存,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
Java實(shí)現(xiàn)從jar包中讀取指定文件的方法
這篇文章主要介紹了Java實(shí)現(xiàn)從jar包中讀取指定文件的方法,涉及java針對(duì)jar文件的讀取及查找相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
JUC中的wait與notify方法實(shí)現(xiàn)原理詳解
這篇文章主要介紹了JUC中的wait與notify方法實(shí)現(xiàn)原理,在進(jìn)行wait()之前,就代表著需要爭(zhēng)奪Synchorized,而Synchronized代碼塊通過(guò)javap生成的字節(jié)碼中包含monitor?enter和monitor?exit兩個(gè)指令2023-03-03
mybatis定義sql語(yǔ)句標(biāo)簽之delete標(biāo)簽解析
這篇文章主要介紹了mybatis定義sql語(yǔ)句標(biāo)簽之delete標(biāo)簽解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringMVC4+MyBatis+SQL Server2014實(shí)現(xiàn)數(shù)據(jù)庫(kù)讀寫(xiě)分離
這篇文章主要介紹了SpringMVC4+MyBatis+SQL Server2014實(shí)現(xiàn)讀寫(xiě)分離,需要的朋友可以參考下2017-04-04
Java實(shí)現(xiàn)冒泡排序算法及對(duì)其的簡(jiǎn)單優(yōu)化示例

