java - 如何使用 Jackson 反序列化外部 Lombok 构建器类

标签 java jackson mixins builder lombok

我有一个第 3 方 Lombok 构建器 POJO,我无法修改它,我想使用 jackson 对其进行序列化。值得注意的是,它没有有一个 NoArgsConstructor。

@Data
@Builder
public class ExternalClass {
   private String name;
   private String data; 
   // etc.
} 

从表面上看,这似乎很简单,但在实践中却令人难以置信地令人沮丧,因为每个可能的选项似乎都被不同的并发症所抵消。本质上,我很难让一个外部 Lombok builder 与 jackson mixin 一起工作。

Lombok 生成样式为 .name(String name) 的流畅 setter,而 Jackson 的内置构建器反序列化器需要 .withName(String name)。 Lombok 文档和其他地方的食谱,例如 here建议在预先声明的内部 stub 生成器上结合使用 @JsonDeserialize(builder=ExternalClass.ExternalClassBuilder.class)@JsonPOJOBuilder(withPrefix="")。但这是不可能的,因为 Lombok 类在外部库中。

将这些注解应用到混入中没有任何效果。

@JsonDeserialize(ExternalClass.ExternalClassBuilder.class)
public abstract class ExternalClassMixin {
   @JsonPOJOBuilder(withPrefix="")
   public static ExternalClassBuilder {
   }
} 

我发现唯一可行的方法是利用由 @Builder 创建的包访问 AllArgsConstructor 并使用以下构造函数填充 mixin

public abstract class ExternalClassMixin {
   @JsonCreator public ExternalClassMixin(
      @JsonProperty("name") String name,
      @JsonProperty("data") String data,
      // etc.
  ) {} 
} 

这显然是不可取的,因为它需要显式地迭代和硬编码每个类属性,使得 mixin 容易受到外部 POJO 中的任何更改的影响。

我的问题是 - 是否有一种健壮的、可维护的方法来使用 Jackson 序列化这个外部构建器类而不修改它,使用 mixin 或者可能是一个完整的反序列化器?

更新

我实现了@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);
   }
}

最佳答案

您可以按如下方式自定义您的 ObjectMapper:

    ObjectMapper mapper = new ObjectMapper();
    mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
        @Override
        public Class<?> findPOJOBuilder(AnnotatedClass ac) {
            if (ExternalClass.class.equals(ac.getRawType())) {
                return ExternalClass.ExternalClassBuilder.class;
            }
            return super.findPOJOBuilder(ac);
        }

        @Override
        public Value findPOJOBuilderConfig(AnnotatedClass ac) {
            if (ac.hasAnnotation(JsonPOJOBuilder.class)) {
                return super.findPOJOBuilderConfig(ac);
            }
            return new JsonPOJOBuilder.Value("build", "");
        }
    });

这将

  • 明确配置 ExternalClass 的反序列化使用其构建器,并且
  • 将构建器 setter 方法的默认前缀设置为 ""(存在 @JsonPOJOBuilder 注释时除外)。

如果您不想在 findPOJOBuilder() 中显式列出所有外部类,您当然可以通过编程方式查看该类以检查它是否具有看起来像构建器的内部类。

关于java - 如何使用 Jackson 反序列化外部 Lombok 构建器类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54350527/

相关文章:

Python Django - "AUTH_USER_MODEL refers to model ' %s' 尚未安装”% settings.AUTH_USER_MODEL

c# - 算法 - java、c# 或 delphi - 在数组中搜索大于 arraySize/2 的数字。一次通过,无需额外内存

java - 是什么让 WildFly 自动取消部署 EAR?

java - 如何使用 Jackson 将列表内容序列化为平面 JSON 对象?

java - JSONObject 与列表到字符串到 JsonNode

java - 为什么使用 spring MVC 进行对象到 json 转换在这种情况下不起作用?

css - less.js 守卫和条件

date - Dateish 字符串的问题

java - 在没有root的计算机上格式化hadoop中的namenode

java - 创建子类只是为了在不同子类之间进行转换