使@JsonAnySetter 与@Value Lombok 一起工作

Mon*_*nta 3 java jackson lombok

我有一个具有很多属性(~80 个属性)的 json 对象,我想在 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);
   }

}
Run Code Online (Sandbox Code Playgroud)

Jan*_*eke 7

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

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

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

    @JsonAnySetter
    @Singular("any")
    private Map<String, Object> any;
}
Run Code Online (Sandbox Code Playgroud)

较旧的龙目岛版本

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

自定义 lombok 构建器可以通过简单地将其内部类标头添加到您的类中来完成。Lombok 检测到已经有一个 builder 类,只是添加了所有不存在的东西。这意味着您可以添加自己的方法,如果这些方法恰好与 lombok 生成的方法同名,lombok 将跳过此方法。

使用这种方法,我们将构建器的 setter 方法替换为“any”,@JsonAnySetter并向其添加 required 。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));
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答。尽管我对@JsonAnyGetter 也有类似的问题,但它还是有帮助的。就我而言,要使 Jackson 与 Lombok 配合使用,我只需在“Map”字段之前应用“@Getter(onMethod_ = @JsonAnyGetter)”即可。我没有使用@Jacksonized、@Builder 或@Singular。我发布此内容只是为了对其他人有帮助!再次感谢! (2认同)