简体   繁体   English

你如何通过 Jackson 2 JsonNode 遍历 JSON?

[英]How do you tree walk JSON via Jackson 2 JsonNode?

This was a bit of an exercise in frustration made worse by the fact that I couldn't find any answers to this question.由于我找不到这个问题的任何答案,这有点让人沮丧。 So I'm going to answer the question here.所以我要在这里回答这个问题。

What I find most difficult to understand was that JsonNode doesn't have any getName() or similar method which I was expecting given that JSON is a name:value data type.我发现最难理解的是 JsonNode 没有任何getName()或类似的方法,我期望 JSON 是name:value数据类型。 Though I realised after working out this solution that arrays aren't name:value.虽然我在解决这个解决方案后意识到 arrays 不是名称:值。

See answer below.请参阅下面的答案。

package treeWalker;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;

public class TreeWalker
{
    public JsonNode convertJSONToNode(String json) throws JsonProcessingException, IOException
    {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode = mapper.readTree(json);

        return jsonNode;
    }

    public void walkTree(JsonNode root)
    {
        walker(null, root);
    }

    private void walker(String nodename, JsonNode node)
    {
        String nameToPrint = nodename != null ? nodename : "must_be_root";
        System.out.println("walker - node name: " + nameToPrint);
        if (node.isObject())
        {
            Iterator<Map.Entry<String, JsonNode>> iterator = node.fields();

            ArrayList<Map.Entry<String, JsonNode>> nodesList = Lists.newArrayList(iterator);
            System.out.println("Walk Tree - root:" + node + ", elements keys:" + nodesList);
            for (Map.Entry<String, JsonNode> nodEntry : nodesList)
            {
                String name = nodEntry.getKey();
                JsonNode newNode = nodEntry.getValue();

                // System.out.println("  entry - key: " + name + ", value:" + node);
                walker(name, newNode);
            }
        }
        else if (node.isArray())
        {
            Iterator<JsonNode> arrayItemsIterator = node.elements();
            ArrayList<JsonNode> arrayItemsList = Lists.newArrayList(arrayItemsIterator);
            for (JsonNode arrayNode : arrayItemsList)
            {
                walker("array item", arrayNode);
            }
        }
        else
        {
            if (node.isValueNode())
            {
                System.out.println("  valueNode: " + node.asText());
            }
            else
            {
                System.out.println("  node some other type");
            }
        }
    }
}

And a Unit test to exercise (with no asserts! Sorry). 还有一个单元测试要练习(没有断言!对不起)。

package treeWalker;

import java.io.IOException;

import org.junit.Test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;


public class TreeWalkerTest
{
    TreeWalker treeWalker = new TreeWalker();

    private String getJSON()
    {
        String json = "{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":[1,2,3]}";
        return json;
    }

    @Test
    public void testConvertJSONToNode() throws JsonProcessingException, IOException
    {
        String json = getJSON();

        JsonNode jNode = treeWalker.convertJSONToNode(json);

        System.out.println("jnode:" + jNode);

    }

    @Test
    public void testWalkTree() throws JsonProcessingException, IOException
    {
        JsonNode jNode = treeWalker.convertJSONToNode(getJSON());

        treeWalker.walkTree(jNode);
    }
}

Oh, and the build.gradle : 哦,还有build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.5'
    compile 'com.fasterxml.jackson.core:jackson-core:2.4.3'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.4.3'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.3'
    compile 'com.google.guava:guava:18.0'

    testCompile "junit:junit:4.11"
}

This is just an updated variation on HankCa's excellent answer.这只是 HankCa 出色答案的更新变体。 Under Java 8 and later, you can use Iterator.forEachRemaining() to loop through and you can externalize the consumer.在 Java 8 及以后,可以使用 Iterator.forEachRemaining() 循环遍历,可以将消费者外部化。 Here's an updated version:这是一个更新版本:

package treeWalker;

import java.io.IOException;
import java.util.function.BiConsumer;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TreeWalker
{
    public JsonNode convertJSONToNode(String json) throws JsonProcessingException, IOException
    {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode = mapper.readTree(json);

        return jsonNode;
    }

    public void walkTree(JsonNode root, BiConsumer<String, String> consumer)
    {
        walker(null, root, consumer);
    }

    private void walker(String nodename, JsonNode node, BiConsumer<String, String> consumer)
    {
        String nameToPrint = nodename != null ? nodename : "must_be_root";
        if (node.isObject())
        {
            node.fields().forEachRemaining(e->walker(e.getKey(), e.getValue(), consumer));
        }
        else if (node.isArray())
        {
            node.elements().forEachRemaining(n->walker("array item of '" + nameToPrint + "'", n, consumer));
        }
        else
        {
            if (node.isValueNode())
            {
                consumer.accept(nameToPrint, node.asText());
            }
            else
            {
                throw new IllegalStateException("Node must be one of value, array or object.");
            }
        }
    }
}

Here's the unit test class (Now in Junit5):这是单元测试 class(现在在 Junit5 中):

package treeWalker;

import java.io.IOException;

import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;


public class TreeWalkerTest
{
    TreeWalker treeWalker = new TreeWalker();

    private String getJSON()
    {
        String json = "{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":[1,2,3]}";
        return json;
    }

    @Test
    public void testConvertJSONToNode() throws JsonProcessingException, IOException
    {
        String json = getJSON();

        JsonNode jNode = treeWalker.convertJSONToNode(json);

        System.out.println("jnode:" + jNode);

    }

    @Test
    public void testWalkTree() throws JsonProcessingException, IOException
    {
        JsonNode jNode = treeWalker.convertJSONToNode(getJSON());

        treeWalker.walkTree(jNode, (a,b)->System.out.println("name='" + a + "', value='" + b + "'."));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM