spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.63k stars 38.14k forks source link

Reading typed lists with RestTemplate [SPR-8263] #12911

Closed spring-projects-issues closed 9 years ago

spring-projects-issues commented 13 years ago

Craig Walls opened SPR-8263 and commented

With RestTemplate's methods, it is possible to request an object of a specific type...e.g.:

Foo foo = restTemplate.getForObject("some uri", Foo.class);

But if I want to retrieve a list of Foos, this won't work:

List\ foos = restTemplate.getForObject("some uri", List.class);

Because there's no way to specify the type of the List to return, I get back a List of Map instead. It'd be nice if there was a way to specify the List's generic type so that I can get back a List\ and not have to extract Foo objects from Map objects.


1 votes, 4 watchers

spring-projects-issues commented 13 years ago

Craig Walls commented

I forgot to mention that the other way to handle this is to either pass in a class that extends ArrayList\...

List\ foos = restTemplate.getForObject("some uri", MyFooList.class); // MyFooList extends ArrayList\

...or if this is JSON in the response, I can create a holder class whose constructor takes a List\ and is annotated with @JsonCreator.

These work, but are really workarounds for not being able to specify a collection's type when requesting it with RestTemplate.

spring-projects-issues commented 13 years ago

Mike Youngstrom commented

Another workaround is to use an array:

Foo[] foos = restTemplate.getForObject("some uri", new Foo[0].getClass());

spring-projects-issues commented 13 years ago

Arjen Poutsma commented

The problem I see is that Lists would only work for certain media types, such as JSON, and perhaps XML. But even with these two media types I can see a lot of problems, as they both represent a tree structure (and not a sequence). JSON (or Jackson, rather) has some nice workarounds for this as shown above, but JAXB (for instance) does not, AFAIK.

We could create some arbitrary way to convert these tree structures into a list, but I think that will cause more bugs than it will solve.

Resolving as won't fix.

spring-projects-issues commented 9 years ago

chris marx commented

You can return a typed list by doing:

ResponseEntity<? extends ArrayList<User> responseEntity = restTemplate.getForEntity(restEndPointUrl, (Class<? extends ArrayList<User>)ArrayList.class, userId);

and for a generic entity:

ResponseEntity<? extends ArrayList<HashMap<String,Object>>> responseEntity = restTemplate.getForEntity(restEndPointUrl, (Class<? extends ArrayList<HashMap<String,Object>>>)ArrayList.class, parameterId);
spring-projects-issues commented 9 years ago

Bogdan Calmac commented

Arjen, you wouldn't need to convert a tree to a list. If the invoker were able to pass in the information that a List<Foo> is expected, the un-marshaling of Foo would take care of building the tree.

We could have a separate set of methods getForObjectList(...) that takes as parameter the class of the elements of the list.

However, with the existing API we can use Foo[].class to return a Foo[] and this is a decent workaround in my opinion.

spring-projects-issues commented 9 years ago

Sébastien Deleuze commented

If I am understanding correctly what is discussed here, you may consider using ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType) instead. See this javadoc for more details, and also #17745 for same kind of need applied to the request body (planned for 4.3).