当我们在数据表中存储的是json字符串的时候,映射到实体类的时候,Java中只有String类型能和json字符串对应。
那么,如果我们想把json字符串反序列化成对象,有什么办法嘛?
利用Getter、Setter方法
在序列化、反序列化的时候,都要调用实体类的利用Getter、Setter方法,我们可以利用这个特点,在Getter方法中进行反序列化,在Setter方法中进行序列化。当然,序列化的方法可以使用Jackson或者FastJson。
缺点:
- 如果某个类中有需要序列化、反序列化的属性,那就得修改这个类的Getter、Setter方法,无法做到通用。
- 有一种观点认为不应该在实体类中写业务逻辑
利用JPA的Converter
我们利用JPA的converter,并在实体类中指定要使用的converter,达到序列化和反序列化的效果。
可以将实体的属性反序列化为Map<String,Object>和List
- 编写converter需要实现AttributeConverter<T,K>接口,T是Java实体中的属性类型,K是数据表中字段的数据类型
- 需要加上@Converter注解
- Jackson序列化主要调用writeValueAsString方法,反序列化主要调用readValue方法
- 使用SpringBoot内置的Jackson进行序列化,可以通过依赖注入的方式注入ObjectMapper
1 | /** |
实体类中使用@convert注解标明要使用的converter。
1 | .class) (converter = MapAndJson |
缺点:
- 使用Map和List这种结构,无法调用业务类的方法。例如List
可以调用Spec这个类的业务方法。而使用List - 如果有多个实体类需要序列化、反序列化,需要编写多个Converter
我们追求一种通用的写法,可不可以利用泛型呢?
上面的Converter方法中可以使用泛型来达到一种通用的效果,但是Java中泛型是有缺点的。主要体现在反序列化的第二个参数,如果直接使用T.class是不行的。所以我们需要一种机制可以将Class传入到Converter中,但是JPA的Converter无法做到这一点。
1 | return objectMapper.readValue(dbData, HashMap.class); |
我们尝试自己编写一个工具类来实现序列化和反序列化的功能。这样就可以通过传参的方式传入Class。
1 | /** |
这里因为注入了ObjectMapper对象,所以需要加上@Component注解。同时,这里还巧妙的利用了setter方法注入static的对象。
同时,在实体类中需要使用Getter、Setter方法来处理。
1 | // ...省略 |
上面的工具类是比较通用的工具类,但是还不够好。
缺点:
- 需要使用TypeReference来传入参数
注释掉的方法是对不需要传入TypeReference所做的尝试。
一种思路是把List
一种思路是把List