【问题标题】:How to find parent Json node while parsing a JSON如何在解析 JSON 时找到父 Json 节点
【发布时间】:2014-01-02 10:44:44
【问题描述】:

我正在使用 Jackson 解析 JSON 流。

我使用的 API 是 ObjectMapper.readTree(..)

考虑以下流:

{
  "type": "array",
  "items": {
      "id": "http://example.com/item-schema",
      "type": "object",
      "additionalProperties": {"$ref": "#"}
  }
}

现在当我阅读附加属性时,我发现这里定义了一个“$ref”。现在要解析引用,我需要找到它的父代并找出 id(以解析基本架构)。

我找不到任何 API 可以转到持有附加属性的 JsonNode 的父级。有什么办法可以实现吗?

信息:

为什么我需要这个是我需要找到 $ref 必须解决的基本模式。为了弄清楚基本模式,我需要知道其父母的 id..

【问题讨论】:

    标签: java json jackson jsonschema


    【解决方案1】:

    Jackson JSON 树是单链接的,没有父链接。这样做的好处是减少了内存使用(因为可以共享许多叶级节点)和稍微更高效的构建,但缺点是无法向上和向下遍历层次结构。

    因此,您需要自己跟踪,或使用自己的树模型。

    【讨论】:

    • 这不是真的,我正在查看调试器输出,在序列化时,JsonGenerator jgen_writeContext,其中包含 _parent 并一直链接到树。它看起来像是私人的:(
    • 不,这绝对是真的。您在谈论JsonGenerator,它不是树,而是流生成器对象。它有上下文(类似于JsonParser)。但问题是关于没有这种联系的 JSON 树 (JsonNode)。使用流式 API 可以很好地解决原始问题。
    【解决方案2】:

    知道了!

    @Override
    public void serialize(ObjectId value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        JsonStreamContext parent = jgen.getOutputContext().getParent();
        // Win!
    }
    

    【讨论】:

      【解决方案3】:

      我无法理解您的问题的确切背景。但是我正在做一些类似的事情,我必须找到一个属性值,然后如果该值符合某种标准,则对其进行更改。

      为了搜索值节点,我使用了at 函数和JsonPointer 去父我使用JsonPointer.head函数并在根json节点上再次使用at

      示例如下

      ObjectMapper mapper = new ObjectMapper();
      JsonNode rootNode = mapper.readTree(JsonString);
      JsonPointer valueNodePointer = JsonPointer.compile("/GrandObj/Obj/field");
      JsonPointer containerPointer = valueNodePointer.head();
      JsonNode parentJsonNode = rootNode.at(containerPointer);
      
      //above is what you asked for as per my understanding
      //following you can use to update the value node just for 
      //the sake of completeness why someone really look for parent
      //node
      if (!parentJsonNode.isMissingNode() && parentJsonNode.isObject()) {
          ObjectNode parentObjectNode = (ObjectNode) parentJsonNode;
          //following will give you just the field name. e.g. if pointer is /grandObject/Object/field
          //JsonPoint.last() will give you /field 
          //remember to take out the / character 
          String fieldName = valueNodePointer.last().toString();
          fieldName = fieldName.replace(Character.toString(JsonPointer.SEPARATOR), StringUtils.EMPTY);
          JsonNode fieldValueNode = parentObjectNode.get(fieldName);
          if(fieldValueNode != null) {
              parentObjectNode.put(fieldName, 'NewValue');
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-02-26
        • 1970-01-01
        • 1970-01-01
        • 2019-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多