1. 概述
通常情況下,在與 Project Lombok 協作時,我們常常會希望將我們的數據相關的類與像 Jackson 這樣的 JSON 框架結合使用。 鑑於 JSON 在大多數現代 API 和數據服務中得到廣泛應用,這一點尤為重要。
在本快速教程中,我們將探討如何配置我們的 Lombok 構建器類,以便與 Jackson 完美無縫地協同工作.
2. 依賴項
我們需要添加的僅僅是 org.projectlombok
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
當然,我們還需要添加 jackson-databind 依賴項:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.1</version>
</dependency>
3. 一個簡單的水果領域
讓我們定義一個啓用了Lombok的類,其中包含id和名稱,以表示水果:
@Data
@Builder
@Jacksonized
public class Fruit {
private String name;
private int id;
}
讓我們逐步瞭解我們POJO的關鍵註解:
- 首先,我們通過添加 @Data註解來啓動,該註解為簡單的POJO生成的所有通常相關的樣板代碼,例如getter和setter
- 然後,我們添加 @Builder註解——一個使用Builder模式進行對象創建的有用機制
- 最後,最重要的是,我們添加 @Jacksonized註解
簡而言之,@Jacksonized註解是@Builder註解的附加註解。 使用此註解,我們可以自動配置生成的構建器類,使其與Jackson的解序列化工作
請注意,此註解僅在同時存在@Builder或@SuperBuilder註解時才有效。
最後,我們應該提到,雖然@Jacksonized在Lombok v1.18.14中引入,但它仍然被認為是 實驗性功能.
4. 反序列化與序列化
有了我們定義的領域模型,現在可以編寫一個單元測試,使用 Jackson 反序列化一個水果:
@Test
public void withFruitJSON_thenDeserializeSucessfully() throws IOException {
String json = "{\"name\":\"Apple\",\"id\":101}";
Fruit fruit = newObjectMapper().readValue(json, Fruit.class);
assertEquals(new Fruit("Apple", 101), fruit);
}
簡單的 readValue() API 以及 ObjectMapper 已經足夠。我們可以使用它將 JSON 水果字符串反序列化為 Fruit Java 對象。
同樣,我們可以使用 writeValue() API 將 Fruit 對象序列化為 JSON 輸出:
@Test
void withFruitObject_thenSerializeSucessfully() throws IOException {
Fruit fruit = Fruit.builder()
.id(101)
.name("Apple")
.build();
String json = newObjectMapper().writeValueAsString(fruit);
assertEquals("{\"name\":\"Apple\",\"id\":101}", json);
}
該測試展示瞭如何使用 Lombok 建造者 API 構建 Fruit 對象,並且序列化的 Java 對象與預期的 JSON 字符串匹配。
5. 使用自定義構建器
有時我們需要與Lombok為我們生成的構建器實現一起工作,而不是Lombok生成的構建器。例如,當我們的 Bean 的屬性名稱與 JSON 字符串中的字段名稱不同時。
讓我們假設我們想反序列化以下 JSON 字符串:
{
"id": 5,
"name": "Bob"
}
但是我們的 POJO 屬性與字段不匹配:
@Data
@Builder(builderClassName = "EmployeeBuilder")
@JsonDeserialize(builder = Employee.EmployeeBuilder.class)
@AllArgsConstructor
public class Employee {
private int identity;
private String firstName;
}
在這種情況下,我們可以使用 @JsonDeserialize 註解與 @JsonPOJOBuilder註解,並將它們插入到生成的構建器類中以覆蓋 Jackson 的默認值:
@JsonPOJOBuilder(buildMethodName = "createEmployee", withPrefix = "construct")
public static class EmployeeBuilder {
private int idValue;
private String nameValue;
public EmployeeBuilder constructId(int id) {
idValue = id;
return this;
}
public EmployeeBuilder constructName(String name) {
nameValue = name;
return this;
}
public Employee createEmployee() {
return new Employee(idValue, nameValue);
}
}
然後我們可以繼續編寫一個測試,如之前:
@Test
public void withEmployeeJSON_thenDeserializeSucessfully() throws IOException {
String json = "{\"id\":5,\"name\":\"Bob\"}";
Employee employee = newObjectMapper().readValue(json, Employee.class);
assertEquals(5, employee.getIdentity());
assertEquals("Bob", employee.getFirstName());
}
結果表明,儘管屬性名稱不匹配,但一個新的 Employee數據對象已成功從 JSON 源重新創建。
6. 結論
在本文中,我們看到了兩種簡單的配置Lombok構建器類與Jackson無縫協作的方法。
在沒有使用@Jacksonized 註解的情況下,我們必須專門自定義構建器類(們)。但是,使用@Jacksonized 註解,我們就可以使用Lombok生成的構建器類。