Search code examples
javadictionarywebclientspring-webfluxconsuming

How to consume a Map with Spring ClientResponse?


First, I have a REST URL exposed like that:

   @PostMapping("/check/existence")
   @ResponseBody
   public Map<String, MyObjectDto> checkExistence() {
   //some code 

then, I have a consumer with a Spring WebClient, like that :

   ClientResponse response = webclient.post().uri....

I want to do something like that :

   Map<String, MyObjectDto> responseDto = 
   response.bodyToMono(Map.class).block();

but console returns to me

   java.util.LinkedHashMap cannot be cast to  org.mypackage.MyObjectDto

so, how can I consume a map typed like Map<String, MyObjectDto>?


Solution

  • From the documentation of the class ParameterizedTypeReference<T>

    The purpose of this class is to enable capturing and passing a generic Type. In order to capture the generic type and retain it at runtime, you need to create a subclass (ideally as anonymous inline class) as follows:

    When you need to serialize/deserialize something into a type that uses generics (for example Map<k, v> or List)

    You cannot use

    response.bodyToMono(Map.class)
    

    Since this way, spring has no idea what types you want to actually put into the Map. Are you going to put in an int? a String? an Object? It has no idea.

    so instead you need to supply something that includes the type information.

    bodyToMono(new ParameterizedTypeReference<Map<String, MyObjectDto>>() {})
    

    ParameterizedTypeReference is an anonymous class that will hold your type information for you. So the class acts like a vessel to hold your type information as we pass it into the generic function bodyToMono and that way spring can look at the contents of this object and figure out what types you want to use.