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