4

I know that you can implement ObjectMapperCustomizer to configure the mapper for your Quarkus REST service. However, it's not clear in the documentation for Quarkus REST Client, whether it will use that same (global?) mapper or not. And how do you handle the situation when an external service have a different JSON naming convention than your own service? I can't find a way to configure the ObjectMapper for a REST client. I assume you can probably work around this with Jackson annotations, but I'm looking for a way to do it just by configuring an ObjectMapper.

So, basically, the question is: How do I configure a separate ObjectMapper for one specific REST client?

alexsanzdev
  • 101
  • 2
  • 6
  • Spring-boot provides an ObjectMapper in the context. So you can autowire one where ever needed. If you want a custo, global one, just create it in one of your @Configuration classes and inject/autowire as necessary. – Rob Evans May 24 '20 at 15:56
  • Customization can be per type. Check this section in Quarkus Docs : https://quarkus.io/guides/rest-json#configuring-json-support , It gives you two options : JasonB or Jackson. Hope this will help. – iabughosh May 24 '20 at 20:13
  • 1
    Could you please provide a code snippet? Each REST client returns a Response object. Then you can map it to your dto by doing something like that: `client.method.readEntity(MyDto.class)` – Spiros batzio May 27 '20 at 15:00

1 Answers1

9

I ran into the same issue. Through a lot of trial and error I found the following works:

First, define a class that implements JAX-RS ContextResolver:

public class ClientObjectMapper implements ContextResolver<ObjectMapper> {
    @Override
    public ObjectMapper getContext(Class<?> type) {
        ObjectMapper om = new ObjectMapper();
        om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        om.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        om.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
        return om;
    }
}

Then on your client interface simply add @RegisterProvider(ClientObjectMapper.class)

From the testing I've done so far, this will effectively have the same effect as if you were manually constructing the HTTP client using a ClientBuilder.

Kosta
  • 536
  • 1
  • 4
  • 9
  • Great answer. In my case, with Kotlin, I needed to call `findAndRegisterModules()` on the `ObjectMapper` too, to make sure `jackson-module-kotlin` was registered. This probably also applies to any other modules that Quarkus registers automatically. – Adam Millerchip Jul 15 '21 at 12:50
  • Will this work for response.readEntity(MyDto.class) where response is the rest client response? – Avi Oct 17 '22 at 15:57
  • Thanks a lot for the help! Your answer has been improved my understanding of the quarks. Your answer is very useful. – Irina Nov 11 '22 at 17:03
  • Thanks for the solution, it worked like charm, i had an external api that was returning string on error otherwise and object so i wanted to unable ACCEPT_EMPTY_STRING_AS_NULL_OBJECT into the in-build ObjectMapper of RestClient and this solved my problem. – Nikhil Patil Jan 21 '23 at 16:49
  • Is the default objectmapper also not used for rest clients as well ?? Because that can be configured, see the Quarkus guidelines. – Serkan Jan 29 '23 at 17:23