使用 Jackson 与 Lombok 构建器进行反序列化

Ron*_*n U 11 java json jackson lombok

问题

Lombok@builder注释为类创建构建器类。为了支持 json 项的反序列化(使用Jackson 的 ObjectMapper),我添加了以下注释:

@Builder
@JsonDeserialize(builder = Item.ItemBuilder.class)
@JsonPOJOBuilder(withPrefix="")
public class Item {
    @Getter
    String partitionvalue;
}
Run Code Online (Sandbox Code Playgroud)

这是基于@Jacksonized 文档的。关于反序列化器的使用,在存储在AWS S3存储桶中的json文件上,其内容很简单:{"partitionvalue": "test"},我的代码是:

AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
            .withCredentials(new DefaultAWSCredentialsProviderChain())
            .withRegion(region)
            .build();
S3Object s3Object = s3Client.getObject(new GetObjectRequest(bucket, key));
Item item = objectMapper.readValue(s3Object.getObjectContent(), Item.class);
Run Code Online (Sandbox Code Playgroud)

但是,当在 json 文件上运行时,Jackson 失败并显示以下消息:

Unrecognized field "partitionvalue" (class com.example.Test$TestBuilder),
 not marked as ignorable (0 known properties: ])
 at [Source: com.amazonaws.services.s3.model.S3ObjectInputStream@2ca47471; line: 1, column: 21] (through reference chain: com.example.TestBuilder["partitionvalue"])
Run Code Online (Sandbox Code Playgroud)

额外细节

  • 直接使用 @Jacksonized注释效果不太好,因为它是 lombok 实验性的,所以我使用了直接与构建器一起使用所需的注释。

  • 我通过使用 Lombok IntelliJ 插件中的“delombok”选项验证了 Lombok 将执行我对构建器类的期望:

public class Item {
    String partitionvalue;
    Item(String partitionvalue) {
        this.partitionvalue = partitionvalue;
    }
    public static ItemBuilder builder() {
        return new ItemBuilder();
    }
    public String getPartitionvalue() {
        return this.partitionvalue;
    }
    public static class ItemBuilder {
        private String partitionvalue;
        ItemBuilder() { }
        public Item.ItemBuilder partitionvalue(String partitionvalue) {
            this.partitionvalue = partitionvalue;
            return this;
        }
        public Item build() {
            return new Item(partitionvalue);
        }
        public String toString() {
            return "Item.ItemBuilder(partitionvalue=" + this.partitionvalue + ")";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 如果没有@Builder注释(并添加@NoArgsConstructor+ @AllArgsConstructor+ @Setter),它可以正常工作,因此问题不在于 S3 存储桶中的文件或其解析方式。

小智 22

将 lombok-1.18.16 (和 .18)与@Jacksonized注释一起使用对我有用。如果没有该注释,我会得到与您相同的错误。

@Builder
@Jacksonized
public class JsonizerItem {

    @Getter private String partitionvalue;

}
Run Code Online (Sandbox Code Playgroud)
@Test
void test() throws JsonProcessingException {
    JsonizerItem item = new ObjectMapper().readValue("{ \"partitionvalue\" : \"test\"}", JsonizerItem.class);
    assertEquals("test", item.getPartitionvalue());
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢你的回答!但是我选择@Jan Rieke 答案作为接受的答案,因为它提供了直接使用杰克逊化内部注释不起作用的原因。 (3认同)

Jan*_*eke 14

@JsonPOJOBuilder必须放在构建器类上,而不是类本身。如果没有@Jacksonized,您必须自定义生成的构建器类,如下所示:

@Builder
@JsonDeserialize(builder = Item.ItemBuilder.class)
public class Item {
    @Getter
    String partitionvalue;

    @JsonPOJOBuilder(withPrefix="")
    public static class ItemBuilder {}
}
Run Code Online (Sandbox Code Playgroud)