如何在解析JSON时查找父Json节点

时间:2014-01-02 10:44:45

标签: java json jackson jsonschema

我正在使用Jackson解析JSON流。

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

考虑以下流:

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

现在,当我阅读additionalProperties时,我发现这里定义了一个“$ ref”。现在要解析引用,我需要转到它的父节点并找出id(以解析基础架构)。

我找不到任何API转到持有additionalProperties的JsonNode的父级。有没有办法实现这个目标?

的信息:

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

3 个答案:

答案 0 :(得分:11)

杰克逊JSON树是单链接的,没有父链接。这有利于减少内存使用(因为可以共享许多叶级节点)并且构建效率稍高,但是无法在层次结构中上下移动的缺点。

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

答案 1 :(得分:4)

知道了!

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

答案 2 :(得分:0)

我无法理解您问题的确切背景。但我做了一些类似的事情,我必须找到一个属性值,然后在值满足某种标准时更改它。

要搜索我使用at函数的JsonPointer函数的值节点 并转到Parent我使用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');
    }
}