简体   繁体   中英

Custom jackson deserializer for 3rd party library

I'm trying to write custom Jackson deserializers for classes in a third party library. I've made one for one of the basic classes (Duration) but now I'm trying to write the next one for a class (RetryPolicy) that has Duration instances and I'm not quite sure how to proceed. I would like to make use of my Duration deserializer so I don't have to repeat the logic for it.

Here is a code example:

RetryPolicy rp = 
    new RetryPolicy()
    .withRetryInterval(Duration.seconds(2))
    .withBackoff(Duration.seconds(2), Duration.minutes(30), 2)
    .withMaxDuration(Duration.hours(1))
    .withMaxRetries(100);

As I said I already have a deserializer for Duration and if I create a module and add my DurationDeserializer class to it and then register that model to the ObjectMapper, I seem to be almost able to deserializer the following JSON:

{
  "retryInterval": "2 seconds",
  "backoff": {
      "retryInterval": "2 seconds", 
      "maxRetryInterval": "5 minutes", 
      "retryIntervalMultiplier": 2
  },
  "maxDuration": "30 minutes",
  "maxRetries": 100
}

The exception I get is:

Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "backoff" (class net.jodah.lyra.retry.RetryPolicy), not marked as ignorable (5 known properties: , "maxRetries", "maxDuration", "maxRetryInterval", "retryInterval", "retryIntervalMultiplier"])

So it actually seems to be able to fill in all the Duration and int fields by itself (even though this class is using the builder pattern without a build() method. The only thing it's having problems with is the withBackoff(Duration, Duration, int) method.

I'm not quite sure where to go from here. Do I write a custom deserializer for the RetryPolicy class? If so, how to I avoid having to parse all the JSON (for example, I just want to delegate all the Duration variables to my already made DurationDeserializer class)?

I should note (although it's probably obvious) that I cannot annotate the third party library (Duration and RetryPolicy classes) which is why I'm going the custom serializer way.

There are more complex ways that you can do this, but simplest way is to have a look at delegation methods in SerializerProvider (see defaultSerializeValue() ) and DeserializationContext (see findContextualValueDeserializer() ): these objects are passed to your custom (de)serializer. So you can just delegate handling to (de)serializer registered for value types. This is the same approach you would use for any type that you want to handle the default way (whatever mapper is configured with).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM