使@Value Lombok与@JsonAnySetter兼容

7

我有一个 JSON 对象,其中包含许多属性(约 80 个属性),我想将其反序列化为一个 POJO,而无需手动创建所有属性。我可以通过使用 @JsonAnySetter 和一个Map 属性来实现此目的,就像这里描述的那样。

现在我想通过使用 Lombok 使我的 POJO 不可变来实现此目的。我尝试过如下操作,但它只会反序列化 idcode 属性。有没有什么方法可以让它正常工作?

@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);
   }

}
1个回答

12

更新2021-02-01:Lombok v1.18.16

从v1.18.16开始,Lombok会自动将@JsonAnySetter复制到builder的@Singular方法中。与@Jacksonized结合使用,您可以简单地使用以下代码:

@Value
@Jacksonized
@Builder
class Product {
    private String id;
    private String code;

    @JsonAnySetter
    @Singular("any")
    private Map<String, Object> any;
}

较旧版本的 Lombok

对于较旧版本的 Lombok,这需要对生成的构建器类进行一些自定义。

通过简单地将其内部类头添加到您的类中即可定制 Lombok 构建器。Lombok 检测到已经有了一个构建器类,只会添加尚未存在的所有内容。这意味着您可以添加自己的方法,如果这些方法恰好与 Lombok 将生成的方法同名,则 Lombok 会跳过此方法。

采用这种方法,我们替换了构建器的“any”setter 方法,添加了所需的@JsonAnySetter。为了确保顺序相关,我使用 LinkedHashMap 作为映射表;如果无关紧要,您可以使用常规的HashMap

此外,我们还更改了build()方法,以确保向构造函数提供的映射表是不可变的。在这里,我使用 Guava 的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));
        }

    }
}

2
谢谢你的回答。即使我遇到了类似@JsonAnyGetter的问题,它也帮助了我。在我的情况下,为了让Jackson与Lombok配合使用,我只需要在Map字段之前应用@Getter(onMethod_ = @JsonAnyGetter)即可。我没有使用@Jacksonized、@Builder或@Singular。我发表这篇文章只是为了帮助其他人!再次感谢! - Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接