RestTemplate convert response data to class object with generics

One: the case of no generics (here is an example of POST, but the same is true for GET)

CommonResponse response = restTemplate.postForObject(remoteUrl, tokenRequest, CommonResponse.class);

Here tokenRequest is the request body object, which will be serialized into a JSON string by Fastjson. It doesn't matter whether the class it belongs to has a generic type or not, because it can be obtained through member.getClass() (that is, the types of all members in tokenRequest are established). and available);

Two: there are generic cases

CommonResponse<TokenDataModel> response = restTemplate.postForObject(remoteUrl, tokenRequest, CommonResponse.class);

There is a problem at this time, because CommonResponse is generically erased in the bytecode, and all its generic members are essentially a subclass of the Object type, but there is no specific class recorded in .class, so when In the JSON string of the obtained response:

{
    "code": 8209,
    "code_description": "APPLICANT_SUCCESS",
    "data": {
        "cell_phone_number": "1111111111",
        "collect_website": "中国联通","token": "77785fb276ed47cb9a01ec52f9a133c8"
    },
    "message": "成功"
}

RestTemplate will not know how to convert the data part to a generic member. If the T type is considered to be an Object, then obviously Object does not have properties such as cellPhoneNumber, so RestTemplate's approach is to convert the JSON string of the data part. For LinkedHashMap objects (key-value pairs);

Three: the solution

Solved by the exchange method of RestTemplate:

ParameterizedTypeReference<CommonResponse<TokenDataModel>> typeRef = new ParameterizedTypeReference<CommonResponse<TokenDataModel>> () {}; 
// exchange does not correspond to any method, such as GET, POST, PUT, DELETE, so it needs to be specified manually CommonResponse
<TokenDataModel> response = restTemplate.exchange(remoteUrl, HttpMethod.POST, new HttpEntity<>(tokenRequest), typeRef).getBody();

Four: Simply use Fastjson to convert generic classes

CommonResponse<TokenDataModel> response = JSON.parseObject("{json string}", new com.alibaba.fastjson.TypeReference<CommonResponse<TokenDataModel>>(){});

Five: Principle

In java, it is indeed generic erasure after a generic class is compiled into .class, but the actual type of the generic type is (indirectly) stored in the generic class object, so new TypeReference<Test<RealType>>() is required {} yields an object;

Inside it is:

// Get the Generic parent class of the anonymous class object, namely Test<RealType> type
 // Note that superClass is not a Class class object, it should be understood as:
 // One and one generated for the sub-anonymous class object of the generic class Corresponding Type class object (this is like a true generic)
 // This Type class object stores all generic information of this anonymous class object 
Type superClass = getClass().getGenericSuperclass();

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325971596&siteId=291194637