我有一个第三方Lombok构建器POJO,我无法对其进行修改,我想使用jackson对其进行序列化。值得注意的是,没有没有NoArgsConstructor。
export const getCookies = async page => {
const { cookies } = await page._client.send("Network.getAllCookies", {});
return cookies;
};
从表面上看,这似乎很简单,但实际上令人沮丧,因为每种可能的选择似乎都因不同的并发症而被抵消。本质上,我很难让外部龙目岛 builder 与杰克逊 mixin 一起使用。
Lombok产生@Data
@Builder
public class ExternalClass {
private String name;
private String data;
// etc.
}
风格的流利的二传手,而Jackson的内置生成器反序列化器期望.name(String name)
。龙目岛文档以及其他地方的食谱,例如here建议在预先声明的内部存根构建器上结合使用.withName(String name)
和@JsonDeserialize(builder=ExternalClass.ExternalClassBuilder.class)
。但这是不可能的,因为Lombok类在外部库中。
将这些注释应用于mixin无效。
@JsonPOJOBuilder(withPrefix="")
我发现唯一可行的方法是利用@JsonDeserialize(ExternalClass.ExternalClassBuilder.class)
public abstract class ExternalClassMixin {
@JsonPOJOBuilder(withPrefix="")
public static ExternalClassBuilder {
}
}
创建的包访问AllArgsConstructor并使用以下构造函数填充mixin
@Builder
这显然是不希望的,因为它需要显式地迭代和硬编码每个类属性,从而使mixin易受外部POJO中任何更改的影响。
我的问题是-是否有一种健壮,可维护的方法来使用Jackson序列化此外部生成器类,而无需使用mixin或完整的反序列化器对其进行修改?
更新
我实现了@ jan-rieke的出色回答,其中包括使用反射来查找内部构建器类的建议。
public abstract class ExternalClassMixin {
@JsonCreator public ExternalClassMixin(
@JsonProperty("name") String name,
@JsonProperty("data") String data,
// etc.
) {}
}
答案 0 :(得分:3)
这可以通过创建两个 mixin 来实现:一个用于 ExternalClass
(指定要使用的构建器),另一个用于 ExternalClass.ExternalClassBuilder
(指定构建器方法中缺少前缀)。>
@JsonDeserialize(builder = ExternalClass.ExternalClassBuilder.class)
public interface ExternalClassMixin {
}
@JsonPOJOBuilder(withPrefix="")
public interface ExternalClassBuilderMixin {
}
这会根据需要序列化和反序列化 JSON:
public static void main(String[] args) throws JsonProcessingException {
String json = "{\"name\": \"The Name\", \"data\": \"The Data\"}";
ObjectMapper mapper = new ObjectMapper()
.addMixIn(ExternalClass.class, ExternalClassMixin.class)
.addMixIn(ExternalClass.ExternalClassBuilder.class, ExternalClassBuilderMixin.class);
System.out.println(mapper.readValue(json, ExternalClass.class));
System.out.println(mapper.writeValueAsString(mapper.readValue(json, ExternalClass.class)));
}
输出:
ExternalClass(name=The Name, data=The Data)
{"name":"The Name","data":"The Data"}
答案 1 :(得分:1)
您可以按照以下步骤自定义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
的反序列化使用其生成器,并且""
(存在@JsonPOJOBuilder
注释时除外)。如果您不想在findPOJOBuilder()
中明确列出所有外部类,则当然可以通过编程方式查看该类,以检查它是否具有看起来像生成器的内部类。