2013-11-26 3 views
1

Я пытаюсь написать специальные десериализаторы Jackson для классов в сторонней библиотеке. Я сделал один для одного из основных классов (Duration), но теперь я пытаюсь написать следующий для класса (RetryPolicy) с экземплярами Duration, и я не совсем уверен, как действовать. Я хотел бы использовать мой десериализатор продолжительности, поэтому мне не нужно повторять логику для него.Пользовательский десериализатор Jackson для сторонней библиотеки

Вот пример кода:

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

Как я сказал, что уже есть десериализатор для продолжительности и если я создаю модуль и добавить мой класс DurationDeserializer к нему, а затем зарегистрировать эту модель в ObjectMapper, I кажется, почти в состоянии десериализатор следующий JSON:

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

исключение я получаю:

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"]) 

Таким образом, на самом деле, похоже, он может заполнить все поля Duration и int самостоятельно (хотя этот класс использует шаблон построителя без метода build(). Единственное, с чем он сталкивается, это метод withBackoff (Duration, Duration, int).

Я не совсем уверен, куда идти отсюда. Я пишу собственный десериализатор для класса RetryPolicy? Если это так, как мне избежать необходимости разбирать все JSON (например, я просто хочу делегировать все переменные Duration для уже сделанного класса DurationDeserializer)?

Я должен отметить (хотя, вероятно, очевидно), что я не могу аннотировать библиотеку сторонних разработчиков (классы Duration и RetryPolicy), поэтому я перехожу к пользовательскому методу сериализации.

ответ

0

Есть более сложные способы, которые вы можете сделать это, но самый простой способ взглянуть на методы делегирования в SerializerProvider (см defaultSerializeValue()) и DeserializationContext (см findContextualValueDeserializer()): эти объекты передаются на пользовательскую (де) сериализатор , Таким образом, вы можете просто делегировать обработку регистратору (de), зарегистрированному для типов значений. Это тот же подход, который вы бы использовали для любого типа, который вы хотите обрабатывать по умолчанию (независимо от того, с кем настроен конфигуратор).

+0

Я пытался понять это, но я все время натыкаюсь на что-то. Я применил десериализатор для класса RetryPolicy, который работает, но он действительно уродлив, так как он повторяет логику десериализации для Duration (это даже делает это не один раз). Вот код для этого: https://github.com/StFS/LyraJacksonDeserializers/blob/master/src/main/java/com/activitystream/lyra/jackson/LyraRetryPolicyDeserializer.java Остальная часть кода находится в этом тот же проект, и я бы очень хотел узнать, как избежать дублирования кода при создании этого десериализатора. – StFS

+0

Да, общее правило состоит в том, что каждый уровень (и отдельный тип) должен обрабатываться одним (де) сериализатором; и что все делегировано. Это можно сделать, и основные типы все это делают. Но это не обязательно означает, что это тривиально. – StaxMan

Смежные вопросы