一.序列化的必要性
在項目當中用到的Json序列化是采用的jackson。
本項目當中JSON序列化反序列化的意義:在用戶登陸模塊當中幢痘,用戶的登陸信息是存儲在session當中的唬格,即session當中存儲user對象。
在項目演進的過程當中颜说,需要使用redis做用戶登陸的分布式緩存购岗,所以用戶的登陸信息是存儲在redis當中的,在redis當中設(shè)置的通用方法如下:
在登陸時放到session當中的是一個user對象门粪,但是在設(shè)計redis的時候設(shè)計的redis的key喊积、value都是String類型,所以需要先將用戶對象序列化為JSON庄拇,在獲取的時候在反序列化為對象注服,所以需要做一個序列戶對象的工具
public static String set(String key,String value)
public static String get(String key)
即value設(shè)置的是string類型,所以要將user對象Json為String字符串措近,然后調(diào)用set方法存儲在redis當中。在使用的時候在使用反序列化為User對象女淑。
二.重要設(shè)置
Json的序列化主要是通過ObjectMapper對象去實現(xiàn)的瞭郑,以下五個要在Json項目初始化的時候進行加載,下載靜態(tài)代碼塊當中即可鸭你。以下設(shè)置默認都是true屈张。
/**
* ALWAYS:設(shè)置對象的所有字段全部列入:所有的字段都進行序列化
* NON_NULL:非null的才會序列化
* NON_DEFAULT:字段沒有默認值(設(shè)置默認值或者設(shè)置的值和默認值相同)的時候不會序列化,若設(shè)置的值和默認值不同袱巨,會參與序列化
* NON_EMPTY:""和空數(shù)組不會出現(xiàn)在序列戶當中
*/
objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
//取消默認轉(zhuǎn)換timestamps的格式阁谆,若為true,則Json格式化后愉老,設(shè)置的時間字段包含timestamps
objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
//自定義日期格式,此處使用的是自己設(shè)置所有的日期格式皆為以下的格式:yyyy-MM-dd HH:mm:ss
objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtils.STANDARD_FORMAT));
/**
* 忽略空bean轉(zhuǎn)json的錯喔
* false:當要json序列化的對象為賦值是空的時候场绿,不要報錯
* true:當要json序列化的對象為賦值是空的時候,會報運行時異常
*/
objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
//反序列化字段
/**
* 忽略在Json對象當中存在嫉入,但是在java對象當中不存在對應(yīng)屬性的問題焰盗,防止錯喔
* 在進行JSon反序列化時璧尸,Json字段當中有一個字段,java實體類當中沒有熬拒,設(shè)置為false不報錯
*/
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
三.代碼
在進行反序列化的過程當中爷光,如果要反序列化為List<User>,或者Map<,>,則反序列化的第二個參數(shù)不能簡單的為Class<T> clazz,因為如果要反序列化為List<User>澎粟,則JackSon或在反序列化時蛀序,將user轉(zhuǎn)為LinkedHashMap,這是不合適的活烙,List<User>.class當然也是錯的徐裸。
所以可以使用JackSon提供的TypeReference, 在調(diào)用的時候只需要將返回值的類型寫上即可瓣颅,如返回值是List<User>倦逐,則第二個參數(shù)那寫為new TypeReference<List<User>>() {}即可
或者也可以重載該方法為:public static <T> T string2Obj(String str, Class<?> collectionClass,Class<?>... elements)
collectionClass返回集合,此處是List.class,elements返回集合參數(shù)宫补,可以是多個(多個使用數(shù)組),此處是User.class.
package com.mall.util;
import com.mall.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;
import java.util.Date;
import java.text.SimpleDateFormat;
@Slf4j
public class JSONUtil {
private static ObjectMapper objectMapper=new ObjectMapper();
static {
/**
* ALWAYS:設(shè)置對象的所有字段全部列入:所有的字段都進行序列化
* NON_NULL:非null的才會序列化
* NON_DEFAULT:字段沒有默認值(設(shè)置默認值或者設(shè)置的值和默認值相同)的時候不會序列化檬姥,若設(shè)置的值和默認值不同,會參與序列化
* NON_EMPTY:""和空數(shù)組不會出現(xiàn)在序列戶當中
*/
objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
//取消默認轉(zhuǎn)換timestamps的格式
objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
//設(shè)置所有的日期格式皆為以下的格式:yyyy-MM-dd HH:mm:ss
objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtils.STANDARD_FORMAT));
/**
* 忽略空bean轉(zhuǎn)json的錯喔
* false:當要json序列化的對象為賦值是空的時候粉怕,不要報錯
* true:當要json序列化的對象為賦值是空的時候健民,會報運行時異常
*/
objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
//反序列化字段
/**
* 忽略在Json對象當中存在,但是在java對象當中不存在對應(yīng)屬性的問題贫贝,防止錯喔
*/
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
/**
* 將對象轉(zhuǎn)換為string
* @param obj秉犹,首先判斷對象是否為null,然后判斷obj是否為String或子類稚晚,崇堵,是則直接返回,因為是T類型客燕,所以要強轉(zhuǎn)以下鸳劳,不是則序列戶為String
* @param <T>:表示將此方法申明為泛型方法,或申明方法只有一個類型T
* @return
*/
public static <T> String obj2String(T obj){
if(obj==null){
return null;
}
try {
return obj instanceof String ? (String)obj:objectMapper.writeValueAsString(obj);
} catch (Exception e) {
log.warn("parse object to string error",e);
return null;
}
}
//將對象轉(zhuǎn)換為string,可以返回格式化好的JSON對象
public static <T> String obj2StringPretty(T obj){
if(obj==null){
return null;
}
try {
return obj instanceof String ? (String)obj:objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (Exception e) {
log.warn("parse object to string error",e);
return null;
}
}
//反序列化:將一個字符串轉(zhuǎn)換為對象
public static <T> T string2Obj(String str,Class<T> clazz){
if(StringUtils.isEmpty(str) || clazz==null){
return null;
}
try {
return clazz.equals(String.class) ? (T)str : objectMapper.readValue(str,clazz);
} catch (Exception e) {
log.warn("parse object to string error",e);
return null;
}
}
/**
* 對于復(fù)雜對象都可以使用后面兩個方法
* 第一個方法:在調(diào)用的時候只需要將返回值的類型寫上即可也搓,如返回值是List<User>赏廓,則第二個剎那火速寫為new TypeReference<List<User>>() {}
* 第二個方法:collectionClass返回集合,elements返回集合參數(shù)傍妒,可以是多個(多個使用數(shù)組)
*/
/**
* 反序列化為集合List<User>,但是傳參數(shù)的時候不能是List<User>.class,所以只能傳User.class或者List.class,但是如果傳入的List.class,
* 那么就會轉(zhuǎn)為LinkedHashMap幔摸,最后決定使用jackSon的TypeReference是一個接口,可以轉(zhuǎn)換為User
*/
public static <T> T string2Obj(String str, TypeReference<T> typeReference){
if(StringUtils.isEmpty(str) || typeReference == null){
return null;
}
try {
return (T)(typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str,typeReference));
} catch (Exception e) {
log.warn("parse object to string error",e);
return null;
}
}
/**
* @param str
* @param collectionClass 颤练?表示是collectionClass,集合的類型
* @param elements 既忆?表示是 ...表示可以傳遞多個參數(shù),多個參數(shù)的時候傳遞數(shù)組即可,集合當中參數(shù)的類型
* @param <T>
* @return
*/
public static <T> T string2Obj(String str, Class<?> collectionClass,Class<?>... elements){
JavaType javaType=objectMapper.getTypeFactory().constructParametricType(collectionClass,elements);
try {
return objectMapper.readValue(str,javaType);
} catch (Exception e) {
log.warn("parse object to string error",e);
return null;
}
}
public static void main(String[] args) {
User u1=new User();
u1.setId(1);
u1.setEmail("codesheep@163.com");
u1.setCreateTime(new Date());
String user1Json=JSONUtil.obj2StringPretty(u1);
log.info("user1Json:{}",user1Json);
/*User u2=new User();
u2.setId(2);
u2.setEmail("codesheep2@163.com");*/
/* List<User> userList= Lists.newArrayList();
userList.add(u1);
userList.add(u2);
*/
/*String user1Json=JSONUtil.obj2String(userList);
String user1JsonPretty=JSONUtil.obj2StringPretty(userList);
log.info("user1Json:{}",user1Json);
log.info("user1JsonPretty:{}",user1JsonPretty);*/
//List<User> userList11=JSONUtil.string2Obj(user1Json,List<User>.class);
//jackson在反序列化的時候尿贫,如果傳入的List.class,那么就會轉(zhuǎn)為LikedHashMap
//TypeReference是一個接口电媳,
/*List<User> userList1=JSONUtil.string2Obj(user1Json, new TypeReference<List<User>>() {
});
List<User> userList2=JSONUtil.string2Obj(user1Json,List.class,User.class);
*/
System.out.println("end");
}
}