使用 Jackson 与 Lombok builder 反序列化
Using Jackson to deserialize with Lombok builder
问题
Lombok's @builder
annotation creates a builder-class for a class. To support deserialization of json items (using Jackson's ObjectMapper),我添加了以下注释:
@Builder
@JsonDeserialize(builder = Item.ItemBuilder.class)
@JsonPOJOBuilder(withPrefix="")
public class Item {
@Getter
String partitionvalue;
}
这是基于@Jacksonized
documentation. On the usage of the deserializer, upon a json file which is stored in AWS S3 bucket,其内容很简单:{"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);
然而,当 运行 在 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"])
额外的细节
直接使用@Jacksonized
注解效果不佳,因为它是 lombok-experimental,所以我直接使用了需要与构建器一起使用的注解。
我通过使用 Lombok IntelliJ 插件中的“delombok”选项验证了 Lombok 将完成我对构建器的期望class:
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 + ")";
}
}
}
- 没有
@Builder
注释(并添加 @NoArgsConstructor
+ @AllArgsConstructor
+ @Setter
)它工作正常,所以问题不在于文件S3 存储桶或其解析方式。
使用带 @Jacksonized
注释的 lombok-1.18.16(和 .18)对我有用。没有那个注解,我会得到和你一样的错误。
@Builder
@Jacksonized
public class JsonizerItem {
@Getter private String partitionvalue;
}
@Test
void test() throws JsonProcessingException {
JsonizerItem item = new ObjectMapper().readValue("{ \"partitionvalue\" : \"test\"}", JsonizerItem.class);
assertEquals("test", item.getPartitionvalue());
}
@JsonPOJOBuilder
必须放在构建器 class 上,而不是 class 本身。如果没有 @Jacksonized
,您必须按如下方式自定义生成的构建器 class:
@Builder
@JsonDeserialize(builder = Item.ItemBuilder.class)
public class Item {
@Getter
String partitionvalue;
@JsonPOJOBuilder(withPrefix="")
public static class ItemBuilder {}
}
问题
Lombok's @builder
annotation creates a builder-class for a class. To support deserialization of json items (using Jackson's ObjectMapper),我添加了以下注释:
@Builder
@JsonDeserialize(builder = Item.ItemBuilder.class)
@JsonPOJOBuilder(withPrefix="")
public class Item {
@Getter
String partitionvalue;
}
这是基于@Jacksonized
documentation. On the usage of the deserializer, upon a json file which is stored in AWS S3 bucket,其内容很简单:{"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);
然而,当 运行 在 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"])
额外的细节
直接使用@
Jacksonized
注解效果不佳,因为它是 lombok-experimental,所以我直接使用了需要与构建器一起使用的注解。我通过使用 Lombok IntelliJ 插件中的“delombok”选项验证了 Lombok 将完成我对构建器的期望class:
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 + ")";
}
}
}
- 没有
@Builder
注释(并添加@NoArgsConstructor
+@AllArgsConstructor
+@Setter
)它工作正常,所以问题不在于文件S3 存储桶或其解析方式。
使用带 @Jacksonized
注释的 lombok-1.18.16(和 .18)对我有用。没有那个注解,我会得到和你一样的错误。
@Builder
@Jacksonized
public class JsonizerItem {
@Getter private String partitionvalue;
}
@Test
void test() throws JsonProcessingException {
JsonizerItem item = new ObjectMapper().readValue("{ \"partitionvalue\" : \"test\"}", JsonizerItem.class);
assertEquals("test", item.getPartitionvalue());
}
@JsonPOJOBuilder
必须放在构建器 class 上,而不是 class 本身。如果没有 @Jacksonized
,您必须按如下方式自定义生成的构建器 class:
@Builder
@JsonDeserialize(builder = Item.ItemBuilder.class)
public class Item {
@Getter
String partitionvalue;
@JsonPOJOBuilder(withPrefix="")
public static class ItemBuilder {}
}