Jackson JSON:从json-tree获取节点名称

Osk*_*ons 49 java json jackson

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

{  
    node1:"value1",
    node2:"value2",
    node3:{  
        node3.1:"value3.1",
        node3.2:"value3.2"
    }
}
Run Code Online (Sandbox Code Playgroud)

我有

JsonNode rootNode = mapper.readTree(fileReader);
Run Code Online (Sandbox Code Playgroud)

并需要类似的东西

for (JsonNode node : rootNode){
    if (node.getName().equals("foo"){
        //bar
  }
}
Run Code Online (Sandbox Code Playgroud)

谢谢.

Sup*_*era 66

对于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());
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*all 63

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


"节点名称"的JSON术语是"密钥".由于JsonNode#iterator() 不包含键,您需要以不同方式迭代:

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

如果您需要查看密钥,可以稍微简化一下JsonNode#fieldNames():

for (String key : rootNode.fieldNames())
{
    if ("foo".equals(key))
    {
        // bar
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您只想找到带密钥的节点"foo",可以直接访问它.与使用循环相比,这将产生更好的性能(恒定时间查找)和更清晰/更清晰的代码:

JsonNode foo = rootNode.get("foo");
if (foo != null)
{
    // frob that widget
}
Run Code Online (Sandbox Code Playgroud)

  • 看起来好像`getFields()`在Jackson 2.0.0中改为`fields()`. (11认同)
  • 鉴于`fieldNames`和`fields`都返回`iterator`,这是[不可迭代](http://stackoverflow.com/questions/2598219/java-why-cant-iterate-over-an-iterator), [回答下面](http://stackoverflow.com/a/18342245/3831137)似乎是正确的解决方案,它使用`hasNext`进行迭代. (6认同)
  • 实际上迭代`Map.Entry <String,JsonNode>条目:rootNode.fields()`也给我同样的错误 (3认同)
  • 遍历 `String key : rootNode.fieldNames()` 给了我 `Can only iterate over an array or an instance of java.lang.Iterable` 错误。任何的想法? (2认同)

Ann*_*wat 11

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
    }
}
Run Code Online (Sandbox Code Playgroud)

另一个,通过使用String迭代器:

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


小智 8

JsonNode root = mapper.readTree(json);
root.at("/some-node").fields().forEachRemaining(e -> {
                              System.out.println(e.getKey()+"---"+ e.getValue());

        });
Run Code Online (Sandbox Code Playgroud)

一行杰克逊 2+

  • 好吧,解决方案很明显了,他应该添加什么样的描述呢? (7认同)
  • 欢迎来到堆栈溢出!请不要只用源代码来回答。尝试提供有关您的解决方案如何工作的精彩描述。请参阅:[如何写出一个好的答案?](https://stackoverflow.com/help/how-to-answer)。谢谢 (2认同)

Chr*_*Geo 7

澄清在这里:

虽然这将工作:

 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())
 }
Run Code Online (Sandbox Code Playgroud)

这不会:

JsonNode rootNode = objectMapper.readTree(file);

while (rootNode.fields().hasNext()) {
    Map.Entry<String, JsonNode> entry = rootNode.fields().next();
    log.info(entry.getKey() + ":" + entry.getValue())
}
Run Code Online (Sandbox Code Playgroud)

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

一定要使用fasterxml库而不是codehaus.