首页 > 解决方案 > java - 如何从Java中的JSON对象获取从父节点到子节点的所有节点?

问题描述

对于给定的 json 对象,我想在 java 中打印从父级到子级的路径中的所有节点。例如,对于以下给定的 json 作为输入:

{"widget": {
    "debug": "on",
    "window": {
        "title": "Sample Konfabulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    },
    "image": { 
        "src": "Images/Sun.png",
        "name": "sun1",
        "hOffset": 250,
        "vOffset": 250,
        "alignment": "center"
    }
}}

预期输出为:

widget.debug
widget.window.title
widget.window.name
.
.
widget.image.src
widget.image.name

我尝试了以下代码。我认为一旦不再遍历节点,我应该删除它,但我不确定如何执行此操作以及它是否是解决方案。

public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
        String inputJson = "{\"widget\": {\"window\": {\"title\": \"Sample Konfabulator Widget\","
                + "\"name\": \"main_window\",\"width\": 500,\"height\": 500},\"image\": { \"src\": \"Images/Sun.png\","
                + "\"name\": \"sun1\",\"hOffset\": 250,\"vOffset\": 250,\"alignment\": \"center\"},\"text\": {"
                + "\"data\": \"Click Here\",\"size\": 36,\"style\": \"bold\",\"name\": \"text1\",\"hOffset\": 250,"
                + "\"vOffset\": 100,\"alignment\": \"center\",\"onMouseUp\": 20}}}";

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = objectMapper.readTree(inputJson);
        StringBuilder sb = new StringBuilder();
        traverse(rootNode, sb);
    }

    private static void traverse(JsonNode node, StringBuilder sb) {
        if (node.getNodeType() == JsonNodeType.OBJECT) {
            traverseObject(node, sb);
        } else {
            throw new RuntimeException("Not yet implemented");
        }
    }

    private static void traverseObject(JsonNode node, StringBuilder sb) {
        node.fieldNames().forEachRemaining((String fieldName) -> {
            JsonNode childNode = node.get(fieldName);
            printNode(childNode, fieldName, sb);
            if (traversable(childNode)) {
                traverse(childNode, sb);
            }
        });
    }

    private static boolean traversable(JsonNode node) {
        return node.getNodeType() == JsonNodeType.OBJECT || node.getNodeType() == JsonNodeType.ARRAY;
    }

    private static void printNode(JsonNode node, String keyName, StringBuilder sb) {
        if (traversable(node)) {
            sb.append(keyName + ".");
            System.out.println(sb.toString());
        } else {
            sb.append(keyName + ".");
            System.out.println(sb.toString());
        }
    }

但得到输出为:

widget.
widget.window.
widget.window.title.
widget.window.title.name.
widget.window.title.name.width.
widget.window.title.name.width.height.
widget.window.title.name.width.height.image.
widget.window.title.name.width.height.image.src.
widget.window.title.name.width.height.image.src.name.
widget.window.title.name.width.height.image.src.name.hOffset.

标签: javajsonjackson

解决方案


当前,您正在使用 的相同实例StringBuilder,并且文本会累积。

重写方法 - 在每次循环迭代时 fork StringBuilders:

    private static void traverseObject(JsonNode node, StringBuilder sb) {

        node.fieldNames().forEachRemaining((String fieldName) -> {
            StringBuilder sb2 = new StringBuilder(sb);
            JsonNode childNode = node.get(fieldName);
            printNode(childNode, fieldName, sb2);
            if (traversable(childNode)) {
                traverse(childNode, sb2);
            }
        });
    }

这给了我想要的结果:

widget.
widget.debug.
widget.window.
widget.window.title.
widget.window.name.
widget.window.width.
widget.window.height.
widget.image.
widget.image.src.
widget.image.name.
widget.image.hOffset.
widget.image.vOffset.
widget.image.alignment.

现在,要摆脱行尾的句点,请不要在此处添加句点:

    private static void printNode(JsonNode node, String keyName, StringBuilder sb) {
        if (traversable(node)) {
            sb.append(keyName + ".");
            System.out.println(sb.toString());
        } else {
            sb.append(keyName); // don't add point
            System.out.println(sb.toString());
        }
    }

推荐阅读