测试代码,可直接复制运行
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class User<T> {
private Integer age;
private T t;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Attribute {
private String attrName;
private Object attrValue;
}
public static void main(String[] args) {
String json = "{\"age\":18,\"t\":{\"attrName\":\"define\",\"attrValue\":123}}";
// User<Attribute> attributeUser = JSON.parseObject(json, new TypeReference<User<Attribute>>(){}); right: 但是写死了代码
Deserialization<Attribute> attributeDeserialization = new Deserialization<>(json);
// 测试序列化是否成功
System.out.println(attributeDeserialization.getUser().getT().getAttrValue()); // X 通用,但是泛型不行
// error:java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.printerx.SFTest$Attribute
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Deserialization<T> {
private String json;
public User<T> getUser() {
return JSON.parseObject(json, new TypeReference<User<T>>(){});
}
}
详情,方便查看

运行报错信息

我平常也用
fastjson
,也用过TypeReference
参数,但也一般是集合那种带泛型,倒是题主的情况或者说想法之前没有想过。确实某种意义来说这种情况的问题在于
TypeReference
写好泛型后是一种Java
语法的规则,但是不可动态编程替换的,也就是写死了的感觉。不过呢,我这次再看注意到
JSON.parseObject
的第二个参数,往往我们一般用XXX.class
或者TypeReference
。而

XXX.class
时,参数的类型并不是Class
,而是Type
这一下注意的点让我瞬间打通任督二脉,哈哈哈
既然是
Type
,那我们知道除了Class
是一种Type
,带泛型的也是一种Type
,这种情况下不就是咱们的ParameterizedType
嘛这就简单了,我们可以根据
User<T>
中需要的类型直接造一个ParameterizedType
即可。我这里选用的是Java
基础库自带的实现sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
当然这个自带的实现用起来是不太美观,你可以用咱们老朋友
apache commons
包下的org.apache.commons.lang3.reflect.TypeUtils;
感觉应该能解决你的问题叭ヾ( ̄▽ ̄)Bye~Bye~