如何克隆 `com.fasterxml.jackson.core.JsonParser`

huangapple go评论70阅读模式
英文:

How to clone `com.fasterxml.jackson.core.JsonParser`

问题

我需要两次解析相同的 JSON 流,第一次是为了识别 JSON 流中数组的长度,下一步是为了解析实体。然而,一开始只有一个 JsonParser 的实例。是否有办法可以克隆它或者创建一个它的副本?因为一旦该实例用于解析,显然就不能被重用来重新解析相同的 JSON 流。
提前感谢您的帮助。

示例:


   static class ResultEntitiesContainer {
     List<ResultEntity> resultEntities;
     // 可用的 getter 和 setter
   }

    void parseEntities(JsonParser parser) {
      // 需要提取实体的数量。
      int count=0;
      ObjectMapper om = new ObjectMapper();
      JsonNode node = om.readTree(parser);
      node = node.get("resultEntities");
      if (node.isArray()) {
        count = node.size();
      }
    
      // 需要解析 JSON 节点中的实体
      ResultEntitiesContainer rec = om.readValue(parser, ResultEntitiesContainer.class);
      
    }

英文:

I need to parse the same json stream twice, one time to identify say the length of array in the json stream, and next to parse the entities. However, there is only a single instance of JsonParser to start with. Is there a way I can clone this or create a copy of this because once the instance is used to parse, it can't be reused for re-parsing the same json stream obviously.
Thanks in advance.

Example:


   static class ResultEntitiesContainer {
     List<ResultEntity> resultEntities;
     // getter and setters available
   }

    void parseEntities(JsonParser parser) {
      // Need to extract number of entities. 
      int count=0;
      ObjectMapper om = new ObjectMapper();
      JsonNode node = om.readTree(parser);
      node = node.get("resultEntities");
      if (node.isArray()) {
        count = node.size();
      }
    
      // Need to parse the entities in the json node
      ResultEntitiesContainer rec = om.readValue(parser, ResultEntitiesContainer.class);
      
    }

答案1

得分: 1

这个答案的目的是解决假设需要克隆JsonParser的问题。

com.fasterxml.jackson.core.JsonParser 是一个公共的抽象类,并且它并没有提供 clone 或类似的方法。
一个抽象类可以被不同的实现所扩展,而 JsonParser.java 的作者无法控制这些实现。
同样,将 JsonParser 克隆作为 void parseEntities(JsonParser parser); 的参数是不安全的,因为 parseEntities 的作者无法确定使用的是哪种实现,以及它是否可以被克隆。

然而,如果你(作为 parseEntities 的作者)对所使用的实现具有控制权,那么安全地克隆已知的实现是可行的(假设这是可能的)。
因此,如果你知道你的类将要使用哪种特定的 JsonParser 实现(或多个实现),你可以尝试只克隆这些已知的实现。
例如,添加并实现一个或多个方法(根据需要):

void parseEntities(MyJsonParser parser);

void parseEntities(MyOtherJsonParser parser);

然后问题就是如何克隆所使用的具体 JsonParser 实现。例如,假设 MyJsonParser 支持克隆,以下可能是有效的。

> void parseEntities(MyJsonParser parser){
>
> MyJsonParser clonedParser = parser.clone(); // 根据具体实现而定
>
> ...
>
> }

英文:

This answer aims to address the question of cloning the JsonParser assuming it is required.

com.fasterxml.jackson.core.JsonParser is a public abstract class and it does not provide a clone or similar method.
An abstract class may be extended by different implementations that the author of JsonParser.java has no control of.
Similarly it is not safe to clone a JsonParser as an argument of void parseEntities(JsonParser parser); because the author of parseEntities cannot be sure which implementation is used and whether it can be cloned.

However if you (as the author of parseEntities) do have control over the used implementations, then it is safe to clone the known implementations (assuming this is possible).
So if you do know which specific implementation (or implementations) of JsonParser your class will be using, you can try and clone specifically these known implementations.
E.g. add and implemented one or more methods (as needed) like:

void parseEntities(MyJsonParser parser);

void parseEntities(MyOtherJsonParser parser);

Then it is a question of cloning the specific implementations of JsonParser that are used. For instance assuming MyJsonParser supports cloning the following could be valid.

> void parseEntities(MyJsonParser parser){
>
> MyJsonParser clonedParser=parser.clone();//depends on implementation
>
> ...
>
> }

答案2

得分: 0

据我所见,没有必要进行两次解析。只需将其解析一次成类型为 ResultEntitiesContainer 的对象,然后计算列表中的元素以获得 count。您可以按照以下方式更改 parseEntities 方法:

void parseEntities(JsonParser parser) {
   ObjectMapper om = new ObjectMapper();

   // 需要解析 json 节点中的实体
   ResultEntitiesContainer rec = om.readValue(parser, ResultEntitiesContainer.class);
   // 需要提取实体数量
   int count = rec.getResultEntities().size();   
}

或者,您可以按照以下方式从 json 节点解析到 ResultEntitiesContainer 对象:

ResultEntitiesContainer rec = om.treeToValue(node, ResultEntitiesContainer.class);

备注:

  • 请仔细检查是否应将 ResultEntitiesContainer 声明为 static
英文:

As far as I can see, there is no need to parse twice. Just parse it once into an object of type ResultEntitiesContainer and count the elements in the list to get count. You could change method parseEntities as follows:

void parseEntities(JsonParser parser) {
   ObjectMapper om = new ObjectMapper();

   // Need to parse the entities in the json node
   ResultEntitiesContainer rec = om.readValue(parser, ResultEntitiesContainer.class);
   // Need to extract number of entities. 
   int count = rec.getResultEntities().size();   
}

Alternatively you can parse to object ResultEntitiesContainer from json node as follows:

ResultEntitiesContainer rec = om.treeToValue(node, ResultEntitiesContainer.class);

Remark:

  • Please double check if ResultEntitiesContainer should be static.

huangapple
  • 本文由 发表于 2020年5月4日 15:17:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/61586970.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定