背景
因为fastjson的安全漏洞问题,项目中不得不将fastjson更换。研究之后决定采用gson做序列化。
场景
因原序列化代码,用在reids中,重写了序列化方法,报序列化bug之后这也误导了我们一段时间。
GSON序列化报错如下:
“class XXX declares multiple JSON fields named XXX”,
可以看出这是序列化字段时出现了错误,添加 transient 关键字 修饰 不需要序列化的字段,便可以解决该序列化问题。
在项目中存在 子类继承父类,且子类transient与父类具有相同的属性,导致gson在序列化时出错。此时只需要添加transient即可(需要分析代码添加到子类还是父类)
@Getter
@Setter
public class BaseDTO<T> {
private transient Long id;
}
@Getter
@Setter
public class ZmsDTO<T> extends BaseDTO<T> {
private Long id;
private String name;
private List<T> childrens = new ArrayList<>();
}
序列化
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
//JSONObject.toJSONString(t, SerializerFeature.WriteClassName).getBytes(IOUtils.UTF8)
Gson gson = new Gson();
String str =gson.toJson(t);
byte[] bytes = new byte[0];
try {
bytes = str.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return bytes;
}
反序列化
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = null;
try {
str = new String(bytes,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//JSONObject.parseObject(str, type, defaultRedisConfig)
Gson gson = new Gson();
return gson.fromJson(str, type);
}
因部分朋友需要demo,现补充一下demo
首先实现自己的序列化方法
/**
* Redis序列化
*
*
*/
public class GsonRedisSerializer<T> implements RedisSerializer<T> {
private Class<T> type;
public GsonRedisSerializer(Class<T> type) {
this.type = type;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
//JSONObject.toJSONString(t, SerializerFeature.WriteClassName).getBytes(IOUtils.UTF8)
Gson gson = new Gson();
String str =gson.toJson(t);
byte[] bytes = new byte[0];
try {
bytes = str.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return bytes;
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = null;
try {
str = new String(bytes,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//JSONObject.parseObject(str, type, defaultRedisConfig)
Gson gson = new Gson();
return gson.fromJson(str, type);
}
}
然后替换Redis的序列化
/**
* Redis配置
*
*
*/
@Configuration
public class RedisConfig {
@Resource
private RedisConnectionFactory factory;
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GsonRedisSerializer<>(Object.class));
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GsonRedisSerializer<>(Object.class));
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}