Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RestTemplate getForEntity map to list of objects

I have a response from URL which looks like:

{"seq":1,"id":"Test1","changes":[{"rev":"1-52f5cdf008ecfbadf621c2939af7bd80"}]}
{"seq":2,"id":"Test2","changes":[{"rev":"1-8ce403a89dc5e7cb4187a16941b3fb7d"}]}
{"seq":3,"id":"Test3","changes":[{"rev":"1-52as7ddfd8ecfbadf621c2939af7bd80"}]}
{"seq":4,"id":"Test4","changes":[{"rev":"1-6yy03a89dc5e7cb45677a16941b3fb7d"}]}

If the mapped object is String, then getting all the changes feed.

ResponseEntity<String> responseEntity = restTemplate.exchange(URL, HttpMethod.GET, requestEntity, String.class);

Whereas, if I happen to use a custom Value object, somethings like:

public class KnChanges {
private long seq;
private String id;
private List changes;

with getter and setter methods, then I'm getting only the first doc change details. Even if the KnChanges[] (array) is used, only the first change is obtained.

Can you please help as to how the JSON list structure mentioned above can be mapped to an object?

Thanks Harsha

like image 731
Harsha Ananthapadmanabha Avatar asked Jun 19 '15 11:06

Harsha Ananthapadmanabha


1 Answers

Some people asked for a better answer with some explaination. So here it is:

As sujim mentioned: You need to

ParameterizedTypeReference<List<KnChanges>> responseType = new ParameterizedTypeReference<List<KnChanges>>() {};
ResponseEntity<List<KnChanges>> resp = restTemplate.exchange(URL, HttpMethod.GET, requestEntity, responseType);
List<KnChanges> list = resp.getBody();

Explaination:

The last parameter of the exchange method call defines the class that gets instantiated when the response is received. The response data will then be mapped to the resulting object. So you need a List.class in fist place. Because you expect a JSON array. Now you need to define the type of the content of that List. Here Java's type erasure throws some stones in your way. As Java removes generic type information at compile-time, you can't just define the expected List to be a List<KnChanges>.class. "Luckily" there is a hack ;) And that hack is new ParameterizedTypeReference<List<KnChanges>>() {}. Provided that object the application is able to read the generic type information at runtime. And therefore is able to map the received data to your Java objects.

As a side-note: There a several implementations of that hack. It's commonly used for dependency injection or mapper systems, where type erasure can sometimes be an issue. Also Googles Guava offers an implementation. See the code for more information. There you can also learn how it's done, if you like.

like image 170
Mario Eis Avatar answered Sep 27 '22 17:09

Mario Eis