will parse the json
In our daily coding work, often encounter such a formulation or json structure
{
"resultcode": "200",
"reason": "成功的返回",
"result": {
"area": "浙江省温州市平阳县",
"sex": "男",
"birthday": "1989年03月08日"
}
}
复制代码
For the provider of the interface, the outermost layer resultcode
reason
and result
these three elements are there. Therefore, we can define such a Response
class
public class Response<T> {
private String resultcode;
private String reason;
private T result;
}
复制代码
The use of generics to decide what the final result is filled to the inside. Of course, here is filled with an object, we tentatively it can be defined as User
the class
public class User {
private String area;
private String sex;
private String birthday;
}
复制代码
Thus, our data will be in accordance with the agreed rules of json example, returned to the caller. As the caller, the machine is receiving this data, we need to define the following classResopnseUser
public class ResopnseUser {
private String resultcode;
private String reason;
private User result;
}
public class User {
private String area;
private String sex;
private String birthday;
}
复制代码
Then we can use fastJson be happy to resolve the
String testJson = "{\"resultcode\":\"200\",\"reason\":\"成功的返回\",\"result\":{\"area\":\"浙江省温州市平阳县\",\"sex\":\"男\",\"birthday\":\"1989年03月08日\"}}";
ResponseUser response1 = JSONObject.parseObject(testJson,ResponseUser.class);
复制代码
We can see, it did get the results we want
Thinking improvements
However, this has a less severe consequences. I docking with each provider an interface, you have to generate a corresponding class. Over time, these special classes will become more and more, will be more deeply nested. Since the provider can abstract a Response
class, then I can deal with that to the provider?
String testJson = "{\"resultcode\":\"200\",\"reason\":\"成功的返回\",\"result\":{\"area\":\"浙江省温州市平阳县\",\"sex\":\"男\",\"birthday\":\"1989年03月08日\"}}";
Response<User> response = JSONObject.parseObject(testJson,Response.class);
复制代码
Unfortunately, our results are not expected, only the outermost data analysis is successful, the inner layer result
remains JSONObject
.
Recourse to universal forum
Lucky thing, in which thousands of engineers not only thought of this approach, and have someone to solve such a problem! Down through a variety of search, we found fastJson provides TypeReference
this class can solve our problems.
String testJson = "{\"resultcode\":\"200\",\"reason\":\"成功的返回\",\"result\":{\"area\":\"浙江省温州市平阳县\",\"sex\":\"男\",\"birthday\":\"1989年03月08日\"}}";
Response<User> response = JSONObject.parseObject(testJson,new TypeReference<Response<User>>(){});
复制代码
Well, we've got the results you want, you can finally unified interface to all of the outermost layer of the return value judgment.
Not stop there
And so on, we did not find any questions for me? Generics will perform at compile time type erasure ah! This is the first time we directly use the Response<User> response = JSONObject.parseObject(testJson,Response.class);
invalid Cause. So, even if we wrote so new TypeReference<Response<User>>(){}
not the same will be erased it? It is a run-time how to get to the actual type we defined? By looking at TypeReference
the source code, the source code is fortunately very simple and less code. First enter is its constructor protected TypeReference()
, through debug we found that the implementation of the second row in the code, it has received written our generics.
Type superClass = getClass().getGenericSuperclass();
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
复制代码
This code is very simple, get to its parent class getGenericSuperclass()
to get to the actual type. Continue to follow up the code, we can see that it calls a native method private native String getGenericSignature0();
to obtain some information to the class and the parent class ClassRepository
and Type
. At this time, we look back to new TypeReference<Response<User>>(){}
actually create an TypeReference
anonymous inner class by class getGenericSuperclass()
, get to the actual type information.
Continue to root out
Let us now look at our income, note must be 2:00:
- Generics will perform at compile time type erasure .
- To acquire its parent class
getGenericSuperclass()
to get to the actual type. Etc., these two are mutually contradictory ah. 1 said no, two said'll find, in the end is how it happened? By looking at the bytecode compiled files, we found the answer. This is the code that containsResponse<User> response = JSONObject.parseObject(testJson,new TypeReference<Response<User>>(){});
information about the methods of the class file decompile. We can see it one moreLocalvariableTypeTable
, which isSignature
exactly the type of information stored in the actual. ** That is not completely erase type, type parameter we still can get by way of reflection. ** called erasing method justcode
byte code erasing property. In addition, we also see theInnerClasses
list, there is an inner class called Main $ 1, this is what wenew TypeReference<Response<User>>(){}
to sum up
- By
JSONObject.parseObject(testJson,new TypeReference<Response<User>>(){});
the way, to solve the problem json nested generics. Convenient, fast and intuitive - You can
getClass().getGenericSuperclass();
get to the real type. Authentication Code
// 这类创建了一个HashMap的匿名子类
HashMap<String,Integer> subIntMap = new HashMap<String,Integer>(){};
System.out.println(subIntMap.getClass().getSuperclass());
Type subClassType = subIntMap.getClass().getGenericSuperclass();
if(subClassType instanceof ParameterizedType){
ParameterizedType p = (ParameterizedType) subClassType;
for (Type t : p.getActualTypeArguments()){
System.out.println(t);
}
}
复制代码
Output
class java.util.HashMap
class java.lang.String
class java.lang.Integer
复制代码
- Type is not completely erased, the type of the parameter can get through reflection. Authentication Code
ResponseUser response = new ResponseUser();
Field field = response.getClass().getField("result");
System.out.println("result Type is "+ field.getType());
System.out.println("result GenericType is "+ field.getGenericType());
public class ResponseUser {
private String resultcode;
private String reason;
public List<User> result;
}
复制代码
Output
result Type is interface java.util.List
result GenericType is java.util.List<com.jd.jr.alpha.cpa.fastJson.User>
复制代码