Джексон JSON: получить имя узла из дерева json - PullRequest
48 голосов
/ 05 октября 2011

Как я могу получить имена узлов из дерева 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
  }
}

спасибо.

Ответы [ 5 ]

64 голосов
/ 20 августа 2013

Для Джексона 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());
}
62 голосов
/ 05 октября 2011

Этот ответ относится к версиям Jackson до 2+ (изначально написано для 1.8). См. @ ответ SupunSameera для версии, которая работает с более новыми версиями Джексона.


Термины JSON для «имени узла» - это «ключ». С JsonNode#iterator() не включает ключи, вам нужно повторить по-другому :

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", вы можете получить к нему прямой доступ . Это даст лучшую производительность (поиск в постоянном времени) и более чистый / понятный код, чем при использовании цикла:

JsonNode foo = rootNode.get("foo");
if (foo != null)
{
    // frob that widget
}
11 голосов
/ 24 июня 2016

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
    }
}

Другой - с помощью итератора String:

Iterator<String> it = jsonNode.getFieldNames();
while (it.hasNext())
{
    String key = it.next();
    if (key.equals(foo))
    {
         //code here
    }
}
7 голосов
/ 01 декабря 2016

Уточнение здесь:

Пока это будет работать:

 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.

0 голосов
/ 26 августа 2018
JsonNode root = mapper.readTree(json);
root.at("/some-node").fields().forEachRemaining(e -> {
                              System.out.println(e.getKey()+"---"+ e.getValue());

        });

В одну строку Джексон 2 +

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...