使用 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 {
}