如何修改集合反序列化器,以使其生成按给定条件过滤掉的集合?

时间:2019-08-30 10:58:26

标签: java json jackson jackson-databind

DOMAIN

有一个Link

public final class Link implements Serializable {

  private final String     _title;
  private final String     _href;
  private final List<Link> _links;

}

有一个类LinkDeserialiser用于从JSON反序列化Link对象

public final class LinkDeserialiser extends JsonDeserializer<Link> {

  @Override
  public Link deserialize(JsonParser parser, DeserializationContext context) throws IOException {
    final JsonNode node = context.readValue(parser, JsonNode.class);
    return Link.builder()
          .title(node.path(Constants.TITLE).asText().trim())
          .href(node.path(Constants.HREF).asText().trim())
          .links(loadLinks(node.path(Constants.LINKS)))
        .build();
  }

}

问题

LinkDeserialiser之前,我们有一个方法

  public static List<Link> readLinks(JsonNode node) {
      List<Link> links = new ArrayList<>();
      node.forEach(childNode -> {
        Link link = new Link(childNode);
        if (link.valid()) {
          links.add(link);
        }
      });
      return links;
  }
已将JsonNode解析为List<Link>并按链接有效性过滤该列表的

。引入LinkDeserialiser时,我们发现了对Link进行反序列化的正确方法,即

nodeParser.readValueAs(new TypeReference<List<Link>>() {});

但是,问题是,我们现在不知道将过滤器link -> link.valid()放在哪里。 nodeParser会在列表中同时填充有效和无效的Link

我不想写一个JsonDeserializer<Collection<Link>>,这似乎是一个沉闷的主意。

问题

我很想回答以下任何一个问题:

1)如何修改集合反序列化器,以使其生成按给定条件过滤掉的集合?

2)有什么方法可以使集合反序列化器“容忍异常”,以便当引发异常时,它将对象收集到集合中吗? (一个例外是一种过滤器)

更新1

Link#valid是一个基本规则,无论上下文和调用者如何,都应遵循。我不想(也不能)强迫调用者通过我的(私有)规则来过滤获得的集合。

更新2

来自CollectionDeserializer

的来源
Object value;
if (t == JsonToken.VALUE_NULL) {
    if (_skipNullValues) {
        continue;
    }
    value = _nullProvider.getNullValue(ctxt);
} else if (typeDeser == null) {
    value = valueDes.deserialize(p, ctxt);
} else {
    value = valueDes.deserializeWithType(p, ctxt, typeDeser);
}
result.add(value);

无论任何条件,似乎都添加了反序列化的value。我正在考虑扩展类并自行过滤结果集合。

1 个答案:

答案 0 :(得分:0)

简短而不复杂:解析所有条目并删除无效的条目。

nodeParser.readValueAs(new TypeReference<List<Link>>() {})
    .removeIf((Link link) -> !link.valid());