我们将REST API编码成JSON格式,然后将它解码到POJO。Jackson的org.codehaus.jackson.map.ObjectMapper“只能”开箱即用,并且在大多数情况下我们并不能做任何其他事情。但有时我们确实需要一个定制的反序列化器以满足我们的定制需求,所以本教程将指导大家如何创建自定义的反序列化。

比方说,我们有以下实体:
public class User {
private Long id;
private String name;
private String email;
public Long getId() {
return id;
}
public User setId(Long id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public User setName(String name) {
this.name = name;
return this;
}
public String getEmail() {
return email;
}
public User setEmail(String email) {
this.email = email;
return this;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("User{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append(''');
sb.append(", email='").append(email).append(''');
sb.append('}');
return sb.toString();
}
}
public class Program {
private Long id;
private String name;
private User createdBy;
private String contents;
public Program(Long id, String name, String contents, User createdBy) {
this.id = id;
this.name = name;
this.contents = contents;
this.createdBy = createdBy;
}
public Program() {}
public Long getId() {
return id;
}
public Program setId(Long id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public Program setName(String name) {
this.name = name;
return this;
}
public User getCreatedBy() {
return createdBy;
}
public Program setCreatedBy(User createdBy) {
this.createdBy = createdBy;
return this;
}
public String getContents() {
return contents;
}
public Program setContents(String contents) {
this.contents = contents;
return this;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Program{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append(''');
sb.append(", createdBy=").append(createdBy);
sb.append(", contents='").append(contents).append(''');
sb.append('}');
return sb.toString();
}
}
让我们序列化/排列第一个对象:
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反序列化到程序对象:
String jsonString = "{"id":1,"name":"Program @# 1","createdBy":{"id":1,"name":"Bazlur Rahman","email":"example@example.com"},"contents":"Some contents"}";
final Program program1 = objectMapper.readValue(jsonString, Program.class);
System.out.println(program1);
现在,假设,这不是真正的情况,我们需要有一个来自于API的不同的JSON,而且这个API不匹配我们的程序类:
{
"id": 1,
"name": "Program @# 1",
"ownerId": 1
"contents": "Some contents"
}
从这个JSON字符串中,你可以看到,它有owenerId这个不同的字段。
现在如果你想像先前我们做的那样序列化此JSON,那么就会出现异常。
有两种方法可以避免异常和这样的序列化:忽略未知字段,或编写自定义的反序列化器。
忽略未知字段
忽略`onwerId`。添加以下注释到程序类中
@JsonIgnoreProperties(ignoreUnknown = true)
public class Program {}
编写自定义的反序列化器
但是有些时候,你确实需要`owerId`这个字段。比方说,你需要涉及用户类的ID。
在这种情况下,你需要编写自定义的解串器:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
public class ProgramDeserializer extends JsonDeserializer<Program> {
@Override
public Program deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);
final Long id = node.get("id").asLong();
final String name = node.get("name").asText();
final String contents = node.get("contents").asText();
final long ownerId = node.get("ownerId").asLong();
User user = new User();
user.setId(ownerId);
return new Program(id, name, contents, user);
}
}
正如你所看到的,首先你得从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.<b>class</b>)
public class Program {}
完整的源代码请见:https://gith

