Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectMapper configuration #75

Closed
lthasle opened this issue Jan 25, 2021 · 5 comments
Closed

ObjectMapper configuration #75

lthasle opened this issue Jan 25, 2021 · 5 comments

Comments

@lthasle
Copy link

lthasle commented Jan 25, 2021

Hi!

Thanks for the answer on my previous issue, it worked nicely.

I think the extension would be more reusable if it was possible to supply own configuration of: com.fasterxml.jackson.databind.ObjectMapper

In my case usage fails with the following:

org.jboss.resteasy.spi.UnhandledException: javax.ws.rs.ProcessingException: com.fasterxml.jackson.databind.exc.InvalidFormatException:
Cannot deserialize value of type java.util.Date from String "2020-12-11T13:15:23.000 +0100": not a valid representation
(error: Failed to parse Date value '2020-12-11T13:15:23.000 +0100': Cannot parse date
"2020-12-11T13:15:23.000 +0100":
while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSX', parsing fails (leniency? null))

If I could apply my own configuration, something like this would solve my case:

@ApplicationScoped public class LogObjectMapper { @Inject ObjectMapper mapper; public ObjectMapper createForLogging() { mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX")); } }

I think the same configuration would be nice for jsonb also.

@SlyngDK
Copy link
Contributor

SlyngDK commented Jan 26, 2021

Hi can you describe the use case where you need this?

@lthasle
Copy link
Author

lthasle commented Jan 26, 2021

Use case:

The application makes an outgoing rest call to an external service and receives a response.
The response contains data and one of the fields is a Date field on the format:
2020-12-11T13:15:23.000 +0100

And in order to be able to successfully deserialize this field, it must be possible to configure it
New DateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX")

Another cases:
The possibility to skip logging of byte[]:

registerModule(new SimpleModule("CustomByteArraySerializer").addSerializer(byte[].class, new CustomByteArraySerializer()));

Include only non empty:

setSerializationInclusion(JsonInclude.Include.NON_EMPTY);

Disable failing on empty beans:

disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

Example of content in CustomByteArraySerializer class:

`public class CustomByteArraySerializer extends ByteArraySerializer {

@OverRide
public void serialize(byte[] value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString("truncated original size: " + value.length);
}
}`

@gsmet
Copy link
Member

gsmet commented Jan 26, 2021

There are 2 options based on CDI to allow you to do that easily:

  • use the ObjectMapperCustomizer core infrastructure with a specific qualifier (I think this would work, if it doesn't we will probably fix it in core) and you would do something similar to the core ObjectMapperProducer but with this specific qualifier.
  • you could produce a @DefaultBean ObjectMapper with a specific qualifier and the user could produce another one and it would replace the @DefaultBean one.

@SlyngDK
Copy link
Contributor

SlyngDK commented Jan 26, 2021

What I think of as the most simple solution is that you use your existing ObjectMapper to convert your object to a JsonNode.
Like this:

@Path("/hello")
public class ExampleResource {
    private Logger log = LoggerFactory.getLogger(ExampleResource.class);

    private ObjectMapper mapper;

    @Inject
    public ExampleResource(ObjectMapper mapper) {
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:sss")); // Just for simplify example
        this.mapper = mapper;
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        // Mapping object to JsonNode using existing ObjectMapper resulting in same json as actual send/received.
        final JsonNode jsonNode = mapper.valueToTree(new Testing());

        log.info("Test", KeyValueStructuredArgument.kv("KEY", jsonNode));

        return "Hello RESTEasy";
    }

    static class Testing {
        private Date now = new Date();

        public Date getNow() {
            return now;
        }
    }
}

Resulting in a log like this:
{"timestamp":"2021-01-26T12:19:45.441+01:00"....,"processId":884,"KEY":{"now":"2021-01-26 12:19:045"}}

@lthasle
Copy link
Author

lthasle commented Jan 26, 2021

gsmet: Thanks for your proposal
From what I can see in the code quarkiverse.loggingjson it use:
JacksonJsonFactory, which configure ObjectMapper
I was not quite sure how to use your suggestion, but was able to use the other suggestion easily, with minor modification in my code.

SlyngDK: Thanks for your proposal, it worked perfect!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants