反序列化后再次使用JsonParser

Ste*_*ger 3 java jackson spring-data

我正在尝试扩展 Jackson 默认反序列化,以便在 json 中显式将占位符对象设置为 null 时将占位符对象分配给我的域对象的字段。我正在使用 Spring Boot + Spring Data。我搜索了很多方法来寻找最好的方法,我相信自定义解串器就是我想要的。我也愿意接受有关于此的建议,但我的实际问题是如何使用默认的反序列化并自己处理显式的空分配。这就是我陷入困境的地方(在 MyItemDeserializer 中):

@Override
public Item deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
        throws IOException, JsonProcessingException
{
    Item item = (Item) defaultDeserializer.deserialize(jsonParser, deserializationContext);
    JsonNode root = jsonParser.readValueAsTree();
    // traverse the tree to handle {"something":null}
    return item;
}
Run Code Online (Sandbox Code Playgroud)

显然,默认反序列化器处理后 jsonParser 对象readValueAsTree返回 null。有没有办法在默认反序列化后将 json 作为树(或其他任何东西)?

Sta*_*Man 7

如果我正确理解你的问题,你想要做的是逆转你拥有的代码:JsonParser你应该首先读取内容,创建JsonParser它们,然后重新使用,而不是按原样传递,然后尝试重新读取那些内容。

一种方法是将内容读取为JsonNode,并使用 构造解析器com.fasterxml.jackson.databind.node.TreeTraversingParser

JsonParser p2 = new TreeTraversingParser(node);
Item item = (Item) defaultDeserializer.deserialize(p2, deserializationContext);
Run Code Online (Sandbox Code Playgroud)

另一种可能性是将内容读取为TokenBuffer,并从中构造 2 个解析器:这是内部代码用于缓冲的内容。这会像这样工作:

TokenBuffer buf = new TokenBuffer(jsonParser);
b.copyCurrentStructure(jsonParser);
JsonParser p2 = buf.asParser(); // for default deserializer
JsonParser p3 = buf.asParser(); // for further processing, read as tree, whatever
Run Code Online (Sandbox Code Playgroud)

尽管在这种情况下构建一棵树有点麻烦。

  • 不,“Node”没有流的概念,它与其源(解析器或显式构建)完全解耦。然而,Node 确实具有可遍历的结构,无论是显式遍历还是构造单独的“TreeTraversingParser”。需要注意的是,在创建解析器时,它最初并不指向任何内容,因此您必须调用“nextToken()”或等效函数。 (3认同)
  • 不知道 TreeTraversingParser。谢谢! (2认同)
  • 最后一个解决方案的更好方法如下:`val tokenBuffer = context.bufferAsCopyOfValue(parser); val jsonNode = context.readTree(tokenBuffer.asParserOnFirstToken())` (2认同)