场景:前后端需要传一个很复杂的参数A,A包含一个List<Object>的列表对象L,L中的每一个成员都可能是不同的Type类型P,fastjson的parseObject()只能将列表L内成员都反序列化成JsonObject类型,因此需要重写fastjson反序列化方法。
github官方文档写的非常不清楚,本文主要结合场景做一个补充。
一、思路
因为A中列表包含多个Object,类型未知,所以需要在包含的所有对象P中都添加一个同类型对象type来记录P的类型, P中再另创建对象value来保存所需参数,总体结构如下图所示。
因此,在自定义反序列时,需要先读取type中存储的class值,通过该值即可得到P的类型。
二、 自定义类实现ObjectReader接口
代码如下,可以使用JSONObject.parseObject()来实现反序列化。
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Map;
// 实现接口
public class ParamReader implements ObjectReader {
public static final ParamReader INSTANCE = new ParamReader();
@Override
public Object readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
if (jsonReader.nextIfNull()) {
return null;
}
// readObject方法:将json字符串转化成K-V形式
Map<String, Object> objectMap = jsonReader.readObject();
// 新建一个目标类A,作为返回的结果
A a= new A();
a.l= new ArrayList<>();
// 读取objectMap中的各个参数并赋给a中
// List<Object> 读取为JSONArray对象
JSONArray parameters = (JSONArray) objectMap.get("l");
for (int i = 0; i < parameters.size(); i ++) {
Type type = JSONObject.parseObject(JSON.toJSONString(parameters.get(i)), Type.class);
// 自定义函数getParamType,获取class类型
Class<?> strClass = getParamType(type);
// 得到strClass即可得到真正的P
Object param = JSONObject.parseObject(JSON.toJSONString(parameters.get(i)), strClass);
// 保存至a中
a.l.add(param);
}
return a;
三、 自定义反序列化的使用
public class Test {
static {
// 注册,这样在反序列化A时才能采用自定义策略
JSON.register(A.class, ParamReader.INSTANCE);
}
public static void main(String[] args) {
// 得到JSON字符串 str
String str = getJSON();
// 此步即可得到反序列化的a
A a = JSONObject.parseObject(str, A.class);
}
}