使用 Jackson 自定義 JSON 反序列化

我們將 rest API 作為 JSON 格式使用,然後將其解組為 POJO。傑克遜的 org.codehaus.jackson.map.ObjectMapper只是工作開箱即用,在大多數情況下我們真的不做任何事情。但有時我們需要自定義反序列化器來滿足我們的自定義需求,本教程將指導你完成建立自定義反序列化程式的過程。

假設我們有以下實體。

public class User {
    private Long id;
    private String name;
    private String email;

    //getter setter are omitted for clarity 
}

public class Program {
    private Long id;
    private String name;
    private User createdBy;
    private String contents;

    //getter setter are omitted for clarity
}

讓我們首先序列化/編組一個物件。

User user = new User();
user.setId(1L);
user.setEmail("example@example.com");
user.setName("Bazlur Rahman");

Program program = new Program();
program.setId(1L);
program.setName("Program @# 1");
program.setCreatedBy(user);
program.setContents("Some contents");

ObjectMapper objectMapper = new ObjectMapper();

final String json = objectMapper.writeValueAsString(program); 的 System.out.println(JSON);

以上程式碼將生成以下 JSON-

{
    "id": 1,
    "name": "Program @# 1",
    "createdBy": {
        "id": 1,
        "name": "Bazlur Rahman",
        "email": "example@example.com"
    },
    "contents": "Some contents"
}

現在可以很容易地做到相反。如果我們有這個 JSON,我們可以使用 ObjectMapper 解組一個程式物件,如下所示 -

現在讓我們說,這不是真實的情況,我們將從 API 中獲得與我們的 Program 類不匹配的不同 JSON。

{
"id": 1,
"name": "Program @# 1",
"ownerId": 1
"contents": "Some contents"
}

檢視 JSON 字串,你可以看到,它有一個與 owenerId 不同的欄位。

現在,如果你想像我們之前所做的那樣序列化這個 JSON,那麼你將有例外。

有兩種方法可以避免異常並將其序列化 -

忽略未知欄位

忽略 onwerId。在 Program 類中新增以下注釋

@JsonIgnoreProperties(ignoreUnknown = true)
public class Program {}

編寫自定義反序列化程式

但是有些情況下你真的需要這個 owerId 欄位。假設你想將它作為 User 類的 id。

在這種情況下,你需要編寫自定義反序列化器 -

如你所見,首先你必須從 JonsParser 訪問 JsonNode。然後,你可以使用 get() 方法輕鬆地從 JsonNode 中提取資訊。你必須確保欄位名稱。它應該是確切的名稱,拼寫錯誤會導致異常。

最後,你必須將你的 ProgramDeserializer 註冊到 ObjectMapper

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Program.class, new ProgramDeserializer());
 
mapper.registerModule(module);
 
String newJsonString = "{\"id\":1,\"name\":\"Program @# 1\",\"ownerId\":1,\"contents\":\"Some contents\"}";
final Program program2 = mapper.readValue(newJsonString, Program.class);

或者,你可以使用註釋直接註冊解串器 -

@JsonDeserialize(using = ProgramDeserializer.class)
public class Program {
}