2011-10-04 28 views
34

¿Cómo puedo recibir los nombres de nodo de un árbol JSON utilizando Jackson? El JSON-File es como la siguiente:Jackson JSON: obtener el nombre de nodo de json-tree

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

tengo

JsonNode rootNode = mapper.readTree(fileReader); 

y necesito algo así como

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

gracias.

Respuesta

46

Esta respuesta se aplica a las versiones de Jackson anteriores a 2+ (originalmente escrito para 1.8). Consulte @SupunSameera's answer para obtener una versión que funcione con las versiones más recientes de Jackson.


Los términos JSON para "nombre de nodo" es "clave". Desde JsonNode#iterator() no incluye teclas, es necesario repetir differently:

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

Si única necesita ver las teclas, puede simplificar las cosas un poco con JsonNode#fieldNames():

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

Y si solo desea encontrar el nodo con la clave "foo", puede access it directly. Esto dará lugar a un mejor rendimiento (de búsqueda constante de tiempo) y el limpiador/código más claro que el uso de un bucle:

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

Parece que 'getFields()' 'cambiado a campos()' en Jackson 2.0.0. –

+1

Iterando a través de 'String key: rootNode.fieldNames()' me da 'Solo puedo iterar sobre una matriz o una instancia de java.lang.Iterable' error. ¿Alguna idea? –

+3

Actualmente iterando a través de 'Map.Entry entry: rootNode.fields() 'también me da el mismo error –

48

Para Jackson 2+ (com.fasterxml.jackson), los métodos son poco diferente:

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()); 
} 
+0

Esto solo itera algunos de los nodos. Estoy viendo algunos nodos que se saltan. – Kieveli

6

fields() y fieldNames() no me funcionaron. Y tuve que pasar bastante tiempo para encontrar una forma de iterar sobre las teclas. Hay dos maneras en que se puede hacer.

Una de ellas es mediante su conversión en un mapa (ocupa más espacio):

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

Otra, mediante el uso de un iterador de la secuencia:

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

Esto fue lo único que funcionó para mí, todas las demás sugerencias fueron causa de bucles infinitos. – ampofila

+0

Muestro que getFieldNames() debería ser fieldNames(). – Switch

1

Aclaración aquí:

Si bien esto funcionará:

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

Esto no:

JsonNode rootNode = objectMapper.readTree(file); 

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

así que tenga cuidado para declarar la Iterator como una variable y el uso que

Cuestiones relacionadas