我有一个具有很多属性(〜80个属性)的json对象,我想在POJO中反序列化而不手动创建所有属性。我可以通过将@JsonAnySetter
与Map
属性一起使用来实现此目的,如here所述。
现在,我想通过使用Lombok使我的POJO不变来完成这项工作。我试过了,但是它只会反序列化id
和code
属性。关于如何使它起作用的任何想法吗?
@Value
@Builder
@EqualsAndHashCode
@JsonDeserialize(builder = Product.ProductBuilder.class)
class Product {
@JsonProperty
private String id;
@JsonProperty
private String code;
@Getter(AccessLevel.NONE)
@Builder.Default
@JsonProperty
private Map<String, Optional<Object>> any = new HashMap<>();
@JsonAnyGetter
public Map<String, Optional<Object>> getAny(){
return this.any;
}
@JsonAnySetter
public void setAny(String key, Optional<Object> value){
this.any.put(key, value);
}
}
目前,这需要对生成的生成器类进行一些自定义。 (在此答案的结尾,我将展望下一个龙目岛版本中的这一点将如何改善。)
自定义lombok构建器可以通过简单地将其内部类头添加到您的类中来完成。 Lombok检测到已经存在一个构建器类,并仅添加所有尚不存在的东西。这意味着您可以添加自己的方法,并且如果这些方法的名称与lombok会生成的方法的名称相同,则lombok会跳过此方法。
[使用这种方法,我们将构建器的setter方法替换为“ any”,并向其中添加所需的@JsonAnySetter
。如果顺序相关,我将LinkedHashMap
用作地图;您可以使用常规的HashMap
。
此外,我们替换build()
方法以确保提供给构造函数的映射是不可变的。我在这里使用番石榴的ImmutableMap
。这将使创建的实例成为不可变的值。
@Value
@Builder
@JsonDeserialize(builder = Product.ProductBuilder.class)
class Product {
@JsonProperty
private String id;
@JsonProperty
private String code;
@Getter(onMethod_ = @JsonAnyGetter)
private Map<String, Object> any;
@JsonPOJOBuilder(withPrefix = "")
public static class ProductBuilder {
@JsonAnySetter
public ProductBuilder any(String anyKey, Object anyValue) {
if (this.any == null) {
this.any = new LinkedHashMap<String, Object>();
}
this.any.put(anyKey, anyValue);
return this;
}
public Product build() {
return new Product(id, code, any == null ? ImmutableMap.of() : ImmutableMap.copyOf(any));
}
}
}
Lombok使用@Singular
批注内置了对不可变地图的支持。更重要的是,它创建了Jackson设置“任何值”所需的确切方法,只是缺少@JsonAnySetter
注释。不幸的是,@Singular
不支持自定义,因此我们无法在此方法中添加@JsonAnySetter
。有一些ongoing work旨在自动将Jackson注释(包括@JsonAnySetter
)复制到构建器的setter方法中。在这种情况下,这将完全消除对构建器定制的需求。释放此功能后,我将更新此答案。