一、背景
近几年fastjson爆出的漏洞非常多,因此可能你所在的公司会要求使用jackson替代fastjson。本文主要就作者自己最近完成fastjson替换记录的一个比较分享。
二、不愿意替换,可升级版本
当然也存在一些系统有很重的历史包袱,或者管理者担心替换带来更大的风险,可能会建议升级,当然也可以选择升级到安全的版本号,目前安全的版本为: 1.2.83 (2023-04-18)
https://github.com/alibaba/fastjson/releases/tag/1.2.83
需要想要替换可以继续往下看
三、自定义一个JsonUtil.java的处理工具类
很多同学在替换的时候都遇到一个很苦恼的事情,很多地方都在使用过JSON、JSONObject、JSONArray,替换起来非常痛苦,主要原因还是之前项目在fastjson使用使用时候缺乏收敛的意识,导致“滥用”,可以借此机会对其进行一个收敛:
import java.io.IOException;
import java.io.StringWriter;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
/**
- json处理工具类
*/
@Slf4j
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
private static ObjectMapper objectMapper1 = new ObjectMapper();
private static JsonFactory factory = new JsonFactory();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper1.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper1.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
}
/**
* @param jsonStr
* @param valueTypeRef new TypeReference<List<T>>(){}
* @param <T>
*
* @return
*/
public static <T> T fromJson(String jsonStr, Class<T> clazz) {
T value = null;
try {
value = objectMapper.readValue(jsonStr, clazz);
} catch (Exception e) {
log.error("fromJson error,jsonStr:" + jsonStr + ",class:" + clazz.getName()
+ ",exception:" + e.getMessage());
throw new RuntimeException(e);
}
return value;
}
/**
* @param jsonStr
* @param valueTypeRef new TypeReference<List<T>>(){}
* @param <T>
*
* @return
*/
public static <T> T fromJson(String jsonStr, TypeReference<?> valueTypeRef) {
T value = null;
try {
value = objectMapper.readValue(jsonStr, valueTypeRef);
} catch (Exception e) {
log.error("fromJson error,jsonStr:" + jsonStr + ",class:" + valueTypeRef.getType()
+ ",exception:" + e.getMessage());
throw new RuntimeException(e);
}
return value;
}
// 需要注意对obj进行判空处理
public static String toJson(Object obj, boolean prettyPrinter) {
if (obj == null) {
return null;
}
StringWriter sw = new StringWriter();
try {
JsonGenerator jg = factory.createGenerator(sw);
if (prettyPrinter) {
jg.useDefaultPrettyPrinter();
}
objectMapper.writeValue(jg, obj);
} catch (IOException e) {
log.error("toJson error,jsonObj:" + obj.getClass().getName() + ",prettyPrinter:" + prettyPrinter
+ ",exception:" + e.getMessage());
throw new RuntimeException(e);
}
return sw.toString();
}
public static String toJsonString(Object object) {
try {
String valueAsString = objectMapper.writeValueAsString(object);
return valueAsString;
} catch (Exception e) {
log.error("toJson error,jsonObj:" + object.getClass().getName() + ",exception:" + e.getMessage());
}
return "";
}
public static String toJsonStringWithDefaultPrettyPrinter(Object object) {
try {
String valueAsString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
return valueAsString;
} catch (Exception e) {
log.error("toJson error,jsonObj:" + object.getClass().getName() + ",exception:" + e.getMessage());
}
return "";
}
public static String object2JsonWithOutMapNull(Object obj) {
try {
return objectMapper1.writeValueAsString(obj);
} catch (IOException e) {
log.warn("object2json error", e);
}
return null;
}
public static <T> T json2ObjectWithOutMapNull(String jsonStr, Class<T> clazz) {
T value = null;
try {
value = objectMapper1.readValue(jsonStr, clazz);
} catch (Exception e) {
log.error("fromJson error,jsonStr:" + jsonStr + ",class:" + clazz.getName() + ",exception:"
+ e.getMessage());
throw new RuntimeException(e);
}
return value;
}
}
四、属性定义&序列化反序列化注解处理
原先:fastjson - @JSONFiled(name = "xxx", ordinal = 2)
替换:jackson - @JsonProperty(value = "xxx", index = 2)
五、Map替换JSONObject
可以替换为Map<String, Object>,如果影响不大,建议直接封装为一个对象。
六、List<Object> 替换JSONArray
JSONArray可以替换为List<Object>
七、Map<String,Long> 类型的序列化与反序列化
需要注意的一个细节,fastjson可以利用TypeReference 复杂类型转换,比如 JSON.parseObject(getNotifyRule(), new TypeReference<Map<String, Long>>() 但是用Jackson,JackUtil.jsonStrToBean(getNotifyRule(), Map.class);转换的时候,不能直接解析为Long,而是Integer