解析JSON, 并将其转换为对应的数据结构。
例如,简单对象,或者复杂的泛型对象
普通对象直接转换
A a = JSON.parseObject(str, A.class);
如果是Map带有泛型的对象,直接转换则格式不正确
// 如果需要Map<String, String>
Map a = JSON.parseObject(str, Map.class)
// 结果不是想要的格式
使用 TypeReference
// 可以直接使用
HashMap<String, String> map = JSONObject.parseObject(str, new TypeReference<HashMap<String, String>>(){});
// 其他类型对象
EnjoyResponseDTO<EnjoyPageResponseDataDTO<Long>> result = JSONObject.parseObject(str, new TypeReference<EnjoyResponseDTO<EnjoyPageResponseDataDTO<Long>>>(){});
// 或者type的构造中使用参数
EnjoyResponseDTO<EnjoyPageResponseDataDTO<T>> result = JSONObject.parseObject(str, new TypeReference<EnjoyResponseDTO<EnjoyPageResponseDataDTO<T>>>(Long.class){});
TypeReference 使用的两种方式,有参或者无参
例子: EnjoyResponseDTO<EnjoyPageResponseDataDTO<Long>> result = JSONObject.parseObject(str, new TypeReference<EnjoyResponseDTO<EnjoyPageResponseDataDTO<Long>>>(){});
等价于:EnjoyResponseDTO<EnjoyPageResponseDataDTO<T>> result = JSONObject.parseObject(str, new TypeReference<EnjoyResponseDTO<EnjoyPageResponseDataDTO<T>>>(Long.class){});
上面的 无参 构造方法 里面 获取了 参数泛型 (ParameterizedType),后面的 有参 构造方法 用参数 替换了 参数泛型中是 泛型变量 里面的 内容。
如果参数中有编译时未知的,执行时才知道的泛型(一般是用来继承中使用泛型),则使用有参构造方法就很有必有了,可以在使用有参的构造之前,获取实际的泛型,作为参数构造出TypeReference
如果 T 是 泛型变量 , 没传后面的修饰参数 T 会被识别成 T 的上边界( 根据 T的定义 如果: <T extends Number> T 被识别为Number,如果是<T> T被识别为 Object)
以下示例为运行未知泛型使用方式
public class TestJSON {
@Test
public void test() {
A a = new A();
Data d = new Data();
Data d2 = new Data();
SimpleData<Data, Data> sd = new SimpleData<>();
sd.data = d;
sd.data2 = d2;
String str = JSON.toJSONString(sd);
System.out.println(str);
SimpleData<Data, Data> data = a.getData(str);
System.out.println(data);
}
}
class A extends B<Data, Data> {
}
abstract class B<T, R> {
public SimpleData<T, R> getData(String str) {
/* 此时T未知类型,不能直接使用无参,会导致T类型变成JSONObject */
return JSON.parseObject(str, new TypeReference<SimpleData<T, R>>(getType(0), getType(1)) {});
}
/* 获取泛型的实际类型 */
protected Type getType(int index) {
Type superClass = getClass().getGenericSuperclass();
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[index];
return type;
}
}
class Data {
public String a = "1";
public String b = "2";
}
/* 带有泛型的数据 */
class SimpleData<T, R> {
public T data;
public R data2;
}