1. 概述
通常情況下,在使用 Project Lombok 時,我們常常會希望將我們的數據相關的類與像 Jackson 這樣的 JSON 框架結合使用。 鑑於 JSON 在大多數現代 API 和數據服務中都非常普遍,這一點尤為重要。
在本快速教程中,我們將探討如何配置我們的 Lombok 構建器類,以便它們能夠無縫地與 Jackson 協同工作。
2. 依賴項
我們需要添加的僅僅是 org.projectlombok 到我們的 pom.xml 中:
<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 和一個 name,以表示一種水果:
@Data
@Builder
@Jacksonized
public class Fruit {
private String name;
private int id;
}讓我們逐步瞭解我們的POJO的關鍵註釋:
- 首先,我們為我們的類添加了 @Data 註解——這會生成與簡單的POJO相關的通常樣板代碼,例如getter和setter
- 然後,我們添加了 @Builder 註解——一種使用Builder模式進行對象創建的有用機制
- 最後,最重要的是,我們添加了 @Jacksonized 註解
為了簡要説明,@Jacksonized 註解是 @Builder 註解的附加註解。 使用此註解可以自動配置生成的Builder類,使其能夠與Jackson的序列化工作,
請注意,此註解只有在同時存在 @Builder 或 @SuperBuilder 註解時才有效。
最後,我們應該提到,儘管 @Jacksonized 註解是在Lombok v1.18.14中引入的,但它仍然被認為是 實驗性功能。
4. 反序列化與序列化
有了我們定義的領域模型,現在讓我們編寫一個單元測試,使用 Jackson 反序列化一個水果:
import org.junit.Test;
import static org.junit.Assert.*;
@Test
public class FruitTest {
@Test
public void testDeserializeFruit() {
// Deserialize a fruit using Jackson
Fruit fruit = new ObjectMapper().readValue("{\"name\":\"Apple\",\"color\":\"Red\"}", Fruit.class);
// Assert that the fruit is correctly deserialized
assertEquals("Apple", fruit.getName());
assertEquals("Red", fruit.getColor());
}
}
@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 構建 Fruit,並且序列化的 Java 對象與預期的 JSON 字符串匹配。
5. 使用自定義構建器
有時,我們可能需要使用自定義構建器實現,而不是Lombok為我們生成的構建器。例如,。
讓我們假設我們想要反序列化以下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 無縫協作。
如果沒有 <em @Jacksonized</em> 註解,我們必須專門自定義構建器類。但是,使用 <em @Jacksonized</em> 允許我們使用 Lombok 生成的構建器類。