【问题标题】:Jackson JSON: get node name from json-treeJackson JSON:从 json-tree 获取节点名称
【发布时间】:2011-12-01 00:20:54
【问题描述】:

如何使用 Jackson 从 JSON 树中接收节点名称? JSON 文件看起来像这样:

{  
    node1:"value1",
    node2:"value2",
    node3:{  
        node3.1:"value3.1",
        node3.2:"value3.2"
    }
}

我有

JsonNode rootNode = mapper.readTree(fileReader);

需要类似的东西

for (JsonNode node : rootNode){
    if (node.getName().equals("foo"){
        //bar
  }
}

谢谢。

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    在此澄清:

    虽然这会起作用:

     JsonNode rootNode = objectMapper.readTree(file);
     Iterator<Map.Entry<String, JsonNode>> fields = rootNode.fields();
     while (fields.hasNext()) {
        Map.Entry<String, JsonNode> entry = fields.next();
        log.info(entry.getKey() + ":" + entry.getValue())
     }
    

    这不会:

    JsonNode rootNode = objectMapper.readTree(file);
    
    while (rootNode.fields().hasNext()) {
        Map.Entry<String, JsonNode> entry = rootNode.fields().next();
        log.info(entry.getKey() + ":" + entry.getValue())
    }
    

    所以要小心将Iterator 声明为变量并使用它。

    请务必使用fasterxml 库而不是codehaus

    【讨论】:

    • rootNode.fields() 无法编译(Java 7)?
    • 那你的Jackson库版本不支持。
    • 这个解决方案没有为我编译,在我的无知中,我拒绝了它,这是我不应该做的。从那以后,我通过另一篇文章 (stackoverflow.com/questions/54205005/…) 了解到,这是由于我使用了较旧的 codehaus jackson,而我本应该使用较新的 fastxml。然而,@ChrisGeo 进行了恶毒的报复:oi65.tinypic.com/dypp5k.jpg Admin 扭转了他的假暂停。
    • 我试了很多次,但我得到“你昨天最后一次对此答案投票。除非编辑此答案,否则你的投票现在已锁定。”。能否请您编辑说您应该使用新的 fastxml 版本的 jackson 而不是 codehaus?
    • 你救了我的一天。您的 While this will work: 正是我一直在寻找的,并且正在为此苦苦挣扎。
    【解决方案2】:
    JsonNode root = mapper.readTree(json);
    root.at("/some-node").fields().forEachRemaining(e -> {
                                  System.out.println(e.getKey()+"---"+ e.getValue());
    
            });
    

    在一条线上杰克逊 2+

    【讨论】:

    • 欢迎来到 Stack Overflow!请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。见:How do I write a good answer?。谢谢
    • 嗯,解决办法很明显了,他应该添加什么样的描述?
    【解决方案3】:

    此答案适用于 2+ 之前的 Jackson 版本(最初为 1.8 编写)。请参阅@SupunSameera's answer 了解适用于较新版本 Jackson 的版本。


    “节点名称”的 JSON 术语是“键”。自JsonNode#iterator() 不包含键,需要迭代differently

    for (Map.Entry<String, JsonNode> elt : rootNode.fields())
    {
        if ("foo".equals(elt.getKey()))
        {
            // bar
        }
    }
    

    如果您需要查看密钥,您可以使用JsonNode#fieldNames() 简化一些事情:

    for (String key : rootNode.fieldNames())
    {
        if ("foo".equals(key))
        {
            // bar
        }
    }
    

    如果你只想找到键为"foo"的节点,你可以access it directly。与使用循环相比,这将产生更好的性能(恒定时间查找)和更清晰/更清晰的代码:

    JsonNode foo = rootNode.get("foo");
    if (foo != null)
    {
        // frob that widget
    }
    

    【讨论】:

    • 看起来getFields() 在 Jackson 2.0.0 中更改为 fields()
    • 遍历String key : rootNode.fieldNames() 给我Can only iterate over an array or an instance of java.lang.Iterable 错误。有什么想法吗?
    • 实际上遍历Map.Entry&lt;String, JsonNode&gt; entry : rootNode.fields() 也会给我同样的错误
    • 鉴于fieldNamesfields 都返回iterator,即not iterableanswer below 似乎是正确的解决方案,它使用hasNext 进行迭代。
    • 我用的是fasterxml 2.6.7,所有的迭代器方法都会导致无限循环。
    【解决方案4】:

    对于 Jackson 2+ (com.fasterxml.jackson),方法略有不同:

    Iterator<Entry<String, JsonNode>> nodes = rootNode.get("foo").fields();
    
    while (nodes.hasNext()) {
      Map.Entry<String, JsonNode> entry = (Map.Entry<String, JsonNode>) nodes.next();
    
      logger.info("key --> " + entry.getKey() + " value-->" + entry.getValue());
    }
    

    【讨论】:

    • 这只会迭代一些节点。我看到一些节点被跳过。
    • 这里需要对入口变量进行空检查吗?
    【解决方案5】:

    fields() 和 fieldNames() 都不适合我。而且我不得不花费相当长的时间来找到一种方法来迭代这些键。有两种方法可以做到。

    一种是将其转换为地图(占用更多空间):

    ObjectMapper mapper = new ObjectMapper();
    Map<String, Object> result = mapper.convertValue(jsonNode, Map.class);
    for (String key : result.keySet())
    {
        if(key.equals(foo))
        {
            //code here
        }
    }
    

    另一个,使用字符串迭代器:

    Iterator<String> it = jsonNode.getFieldNames();
    while (it.hasNext())
    {
        String key = it.next();
        if (key.equals(foo))
        {
             //code here
        }
    }
    

    【讨论】:

    • 这是唯一对我有用的东西,所有其他建议都导致无限循环。
    • 我表明 getFieldNames() 应该是 fieldNames()。
    猜你喜欢
    • 1970-01-01
    • 2020-03-05
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多