У меня есть сторонний конструктор Lombok POJO, который я не могу изменить, и который я хочу сериализовать, используя Джексона. Примечательно, что не имеет NoArgsConstructor.
@Data
@Builder
public class ExternalClass {
private String name;
private String data;
// etc.
}
На первый взгляд это может показаться простым, но на практике это невероятно расстраивает, поскольку каждому возможному варианту противодействует отдельное осложнение. По сути, у меня проблемы с получением внешнего Lombok builder для работы с Джексоном mixin .
Lombok производит плавные сеттеры стиля .name(String name)
, в то время как встроенный десериализатор Джексона ожидает .withName(String name)
. В документации Lombok и других рецептах, таких как здесь , предлагается использовать @JsonDeserialize(builder=ExternalClass.ExternalClassBuilder.class)
в сочетании с @JsonPOJOBuilder(withPrefix="")
в предварительно объявленном конструкторе внутренних заглушек. Но это невозможно, потому что класс Lombok находится во внешней библиотеке.
Применение этих аннотаций к миксину не имеет никакого эффекта.
@JsonDeserialize(ExternalClass.ExternalClassBuilder.class)
public abstract class ExternalClassMixin {
@JsonPOJOBuilder(withPrefix="")
public static ExternalClassBuilder {
}
}
Единственный подход, который я нашел, который работает, - это использовать пакетный доступ AllArgsConstructor, созданный @Builder
, и заполнить миксин следующим конструктором
public abstract class ExternalClassMixin {
@JsonCreator public ExternalClassMixin(
@JsonProperty("name") String name,
@JsonProperty("data") String data,
// etc.
) {}
}
Это, очевидно, нежелательно, поскольку требует явной итерации и жесткого кодирования каждого свойства класса, что делает миксины хрупкими к любым изменениям во внешнем POJO.
У меня вопрос: есть ли надежный и поддерживаемый способ сериализации этого внешнего класса построителя с использованием Джексона без его изменения, с использованием миксина или, возможно, полноценного десериализатора?
Обновление
Я реализовал отличный ответ @ jan-rieke, включая предложение использовать рефлексию для поиска внутреннего класса строителей.
...
public Class<?> findPOJOBuilder(AnnotatedClass ac) {
Class<?> innerBuilder;
try {
innerBuilder = Class.forName(ac.getName()+"$"+ac.getRawType().getSimpleName()+"Builder");
log.info("Builder found: {}", ac.getName());
return innerBuilder;
} catch( ClassNotFoundException e ) {
return super.findPOJOBuilder(ac);
}
}