序列化反序列化
序列化反序列化
当你将一个抽象类序列化反序列化的时候,需要自动反序列化
JacksonPolymorphicDeserialization · FasterXML/jackson-docs Wiki · GitHub
注意,如果只是一个类中的一个属性包含了一个抽象类的话,上面的这个例子就可以解决问题,但是如果是泛型的话,例如 List<XXX>
,光配置注解无效,序列化的时候不会自动填充 property 字段,那怎么办呢,我们可以手动设置 property 属性的值,注意要用实例属性,而不是静态属性,然后我们在代码块中 this.getClass().canonicalName()
获取类名赋值给 property 属性即可。
写点儿代码试试。
写代码描述一下这个问题
- 抽象类
List<抽象类>
new Object[]{List<抽象类> arg}
根据对象类型动态地反序列化地代码参考:
参考:jackson反序列化复杂数据类型(泛型数据类型)_jackson反序列化泛型t-CSDN博客
具体代码请参考 代码实践
fastjson 如何解决复杂对象的序列化和反序列化问题
fastjson 中可以配置将序列化地所有数据的类型信息都放到 json 里面,这样什么类型信息都不会丢失,它可以在序列化时保留对象类型信息,然后在反序列化时根据 json 字符串中的类型信息自动生成对象,用法很简单,只需要 JSONWriter.Feature.WriteClassName
和 JSONReader.Feature.SupportAutoType
结合使用即可。
简单实践
首先得引入 fastjson2 的依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.21</version>
</dependency>
然后使用这两个特性
package xyz.xiashuo;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
/**
* @author xiashuo.xyz
* @date 2024/4/5 11:09
*/
public class FastJsonTest {
String name = "xiasshuo";
public static void main(String[] args) {
// Hero hero = Hero.getList().get(0);
FastJsonTest testObj = new FastJsonTest();
String jsonString = JSONObject.toJSONString(testObj, JSONWriter.Feature.WriteClassName);
FastJsonTest testObjCopy = JSONObject.parseObject(jsonString, FastJsonTest.class, JSONReader.Feature.SupportAutoType);
System.out.println(testObjCopy.name);
}
}
jackson 应该也有类似的配置,TODO
利用 Jackson 实现将方法的所有参数序列化成字符串,然后将字符串反序列化成对象,然后通过反射调用方法
重点是当我们获取参数的 Type 类型之后,如何通过 Jackson 将其反序列化成对象
在使用 Jackson 库时,如果你需要根据 ParameterizedType
动态反序列化泛型类型,可以通过以下步骤来实现。Jackson 提供了一些工具类和方法来处理泛型类型的反序列化。
1. 使用 TypeReference
TypeReference
是 Jackson 提供的一个工具类,可以用来指定泛型的具体类型。通过继承 TypeReference
并指定泛型的具体类型,可以在反序列化时保留类型信息。
示例代码
假设我们有一个泛型类 Response<T>
,我们希望根据 ParameterizedType
动态反序列化具体的类型。
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class JacksonDynamicDeserializationExample {
public static void main(String[] args) {
// 假设这是你从JSON化对象中得到的JSON字符串
String jsonString = "{\"data\":[{\"name\":\"John\", \"age\":30}, {\"name\":\"Jane\", \"age\":25}]}";
// 创建ObjectMapper实例
ObjectMapper objectMapper = new ObjectMapper();
try {
// 获取泛型类型
Type genericType = new GenericType<Response<List<Person>>>(){}.getType();
// 将JSON字符串转换为Response对象
Response<?> response = objectMapper.readValue(jsonString, new TypeReference<Response<List<Person>>>() {});
// 打印对象的属性
for (Person person : (List<Person>) response.getData()) {
System.out.println("Name: " + person.getName() + ", Age: " + person.getAge());
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 定义一个泛型类来获取ParameterizedType
static class GenericType<T> {
private final Type type;
protected GenericType() {
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof ParameterizedType) {
this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
} else {
throw new IllegalArgumentException("Invalid type");
}
}
public Type getType() {
return type;
}
}
}
class Response<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
class Person {
private String name;
private int age;
// 必须提供无参构造函数
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2. 使用 JavaType
JavaType
是 Jackson 提供的另一个工具类,可以用来构建复杂的泛型类型。JavaType
可以通过 ObjectMapper
的 getTypeFactory()
方法创建。
示例代码
假设我们有一个泛型类 Response<T>
,我们希望根据 ParameterizedType
动态反序列化具体的类型。
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class JacksonDynamicJavaTypeExample {
public static void main(String[] args) {
// 假设这是你从JSON化对象中得到的JSON字符串
String jsonString = "{\"data\":[{\"name\":\"John\", \"age\":30}, {\"name\":\"Jane\", \"age\":25}]}";
// 创建ObjectMapper实例
ObjectMapper objectMapper = new ObjectMapper();
try {
// 获取泛型类型
Type genericType = new GenericType<Response<List<Person>>>(){}.getType();
// 构建JavaType
JavaType javaType = objectMapper.getTypeFactory().constructType(genericType);
// 将JSON字符串转换为Response对象
Response<?> response = objectMapper.readValue(jsonString, javaType);
// 打印对象的属性
for (Person person : (List<Person>) response.getData()) {
System.out.println("Name: " + person.getName() + ", Age: " + person.getAge());
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 定义一个泛型类来获取ParameterizedType
static class GenericType<T> {
private final Type type;
protected GenericType() {
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof ParameterizedType) {
this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
} else {
throw new IllegalArgumentException("Invalid type");
}
}
public Type getType() {
return type;
}
}
}
class Response<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
class Person {
private String name;
private int age;
// 必须提供无参构造函数
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
总结
- 使用
TypeReference
可以方便地指定泛型的具体类型,适用于简单的泛型类型。 - 使用
JavaType
可以构建复杂的泛型类型,适用于嵌套泛型或多层泛型的情况。 - 通过这些工具类,Jackson 可以正确地处理泛型类型,从而实现泛型类的动态反序列化。
- 通过定义一个泛型类来获取
ParameterizedType
,可以在运行时获取泛型的具体类型信息。
JavaType 除了 可以通过 constructType 构造之外,还可以通过 constructCollectionType 或者 constructParametricType 等其他方法构造
示例代码
假设我们有一个泛型类 Response<T>
,我们希望将其反序列化为具体的类型。
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class JacksonJavaTypeExample {
public static void main(String[] args) {
// 假设这是你从 JSON 化对象中得到的 JSON 字符串
String jsonString = "{\"data\":[{\"name\":\"John\", \"age\":30}, {\"name\":\"Jane\", \"age\":25}]}";
// 创建ObjectMapper实例
ObjectMapper objectMapper = new ObjectMapper();
try {
// 使用JavaType构建泛型的具体类型
JavaType personListType = objectMapper.getTypeFactory().constructCollectionType(List.class, Person.class);
JavaType responseType = objectMapper.getTypeFactory().constructParametricType(Response.class, personListType);
// 将JSON字符串转换为Response对象
Response<List<Person>> response = objectMapper.readValue(jsonString, responseType);
// 打印对象的属性
for (Person person : response.getData()) {
System.out.println("Name: " + person.getName() + ", Age: " + person.getAge());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Response<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
class Person {
private String name;
private int age;
// 必须提供无参构造函数
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}