我们将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("[email protected]");
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": "[email protected]"
},
"contents": "Some contents"
}

这样做反方向的事情就很容易了。如果我们有这个JSON,那么就可以使用如下的ObjectMapper反序列化到程序对象:

String jsonString = "{\"id\":1,\"name\":\"Program @# 1\",\"createdBy\":{\"id\":1,\"name\":\"Bazlur Rahman\",\"email\":\"[email protected]\"},\"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://github.com/rokon12/json-deserializer

你可能感兴趣的内容
0条评论

dexcoder

这家伙太懒了 <( ̄ ﹌  ̄)>
Owner