2011-10-04 32 views
34

Come posso ricevere i nomi dei nodi da un albero JSON usando Jackson? Il JSON-File simile a questa:Jackson JSON: ottiene il nome del nodo da json-tree

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

ho

JsonNode rootNode = mapper.readTree(fileReader); 

e bisogno di qualcosa come

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

grazie.

risposta

46

Questa risposta si applica alle versioni di Jackson precedenti a 2+ (originariamente scritte per 1.8). Vedi @SupunSameera's answer per una versione che funziona con le versioni più recenti di Jackson.


I termini JSON per "nome nodo" sono "chiave". Dal momento che JsonNode#iterator() non include le chiavi, è necessario iterare differently:

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

Se solo bisogno di vedere i tasti, è possibile semplificare le cose un po 'con JsonNode#fieldNames():

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

E se si desidera trovare il nodo con la chiave "foo", è possibile access it directly. Ciò produrrà migliori prestazioni (ricerca costante di tempo) e pulitore/codice più chiaro rispetto all'utilizzo di un ciclo:

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

Sembra che 'getFields()' 'cambiato in campi()' a Jackson 2.0.0. –

+1

Iterazione tramite 'Chiave stringa: rootNode.fieldNames()' mi dà 'Può solo iterare su un array o un'istanza di errore java.lang.Iterable'. Qualche idea? –

+3

In realtà iterando attraverso la voce 'Map.Entry : rootNode.fields() 'fornisce anche lo stesso errore per me –

48

Per Jackson 2+ (com.fasterxml.jackson), i metodi sono poco differenti:

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

Ciò solo itera alcuni dei nodi. Sto vedendo alcuni nodi saltati. – Kieveli

6

fields() e fieldNames() non funzionavano entrambi per me. E ho dovuto passare un bel po 'di tempo per trovare un modo per scorrere le chiavi. Ci sono due modi in cui può essere fatto.

Uno è convertendolo in una mappa (occupa più spazio):

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

Un altro, utilizzando un iteratore String:

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

Questa è stata l'unica cosa che ha funzionato per me, tutti gli altri suggerimenti sono stati causa di loop infiniti. – ampofila

+0

Mostriamo che getFieldNames() dovrebbe essere fieldNames(). – Switch

1

chiarimento:

Mentre questo funzionerà:

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

Questo non:

JsonNode rootNode = objectMapper.readTree(file); 

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

quindi state attenti a dichiarare la Iterator come una variabile e utilizzare tale

Problemi correlati