数据处理,实现JSON树形结构

前言

所谓从数据库中查询的数据进行树形打印,主要因为一个表中设计了当前记录id和该记录的父级id的字段,使得该表的数据形成了级联的关系。表模拟:

字段类型注释
idint主键id信息
pidint父级id信息,一级设置为0
namevarchar名称属性

通常,我们都是将所有的记录查询出来,在通过业务处理,将数据封装成树形结构。

具体思路我们可以通过递归思想进行数据的处理和封装

具体实现

准备工作:创建一个SpringBoot工程,设计一个Controller组件模拟一个接口。

设计数据实体:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TreeNode {
    private Integer id;
    private String name;
    private Integer pid;
    // childrenNode属性用于保存当前记录的子节点信息
    // 注意:数据中对应的实体没有该字段,我们可以从数据库中查询所有记录后,再使用BeanUtils或MapStruct相关工具进行转换
    private List<TreeNode> childrenNode;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TreeNode treeNode = (TreeNode) o;
        return Objects.equals(id, treeNode.id) && Objects.equals(name, treeNode.name) && Objects.equals(pid, treeNode.pid) && Objects.equals(childrenNode, treeNode.childrenNode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, pid, childrenNode);
    }
}

进行数据处理和封装:

@RestController
@RequestMapping("/treeNode")
@Slf4j
public class HelloController {
    /**
     * 单个父节点模式
     *
     * @return
     */
    @GetMapping("/oneFather")
    public TreeNode listOne() {
        List<TreeNode> nodes = new ArrayList<>();
        // 封装数据:模拟数据数据
        // 注意:从数据库中查询到的数据没有childrenNode属性,那我们可以使用BeanUtils和mapstruct进行对象转换
        Collections.addAll(nodes,
                TreeNode.builder().id(1).pid(0).name("江西省").build(),
                TreeNode.builder().id(2).pid(1).name("吉安市").build(),
                TreeNode.builder().id(3).pid(2).name("遂川县").build(),
                TreeNode.builder().id(5).pid(1).name("赣州市").build(),
                TreeNode.builder().id(6).pid(5).name("章贡").build()
        );
        // 获取树节点
        TreeNode root = nodes.stream().filter(node -> Objects.equals(node.getPid(), 0)).findFirst().orElse(null);
        if (root == null) {
            return null;
        }
        root.setChildrenNode(getChildren(root, nodes));
        return root;
    }

    /**
     * 多个父节点模式
     *
     * @return
     */
    @GetMapping("/manyFather")
    public Set<TreeNode> listMany() {
        List<TreeNode> nodes = new ArrayList<>();
        // 封装数据
        Collections.addAll(nodes,
                TreeNode.builder().id(1).pid(0).name("江西省").build(),
                TreeNode.builder().id(2).pid(1).name("吉安市").build(),
                TreeNode.builder().id(3).pid(2).name("遂川县").build(),
                TreeNode.builder().id(5).pid(1).name("赣州市").build(),
                TreeNode.builder().id(6).pid(5).name("章贡").build(),
                TreeNode.builder().id(7).pid(0).name("浙江省").build(),
                TreeNode.builder().id(8).pid(7).name("杭州").build()
        );
        // 封装树节点
        Set<TreeNode> root = nodes.stream().filter(node -> Objects.equals(node.getPid(), 0)).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(root)) {
            return null;
        }
        // 遍历树节点
        root.stream().forEach(rootNode -> {
            rootNode.setChildrenNode(getChildren(rootNode, nodes));
        });

        return root;
    }

    /**
     * 递归获取根节点的子节点信息
     *
     * @param root  根节点
     * @param nodes 要遍历的节点
     * @return
     */
    private List<TreeNode> getChildren(TreeNode root, List<TreeNode> nodes) {
        List<TreeNode> childrenNodes = nodes.stream()
                // 使用stream流过滤出数据的父级id信息等于根节点的id信息的数据
                .filter(node -> Objects.equals(node.getPid(), root.getId()))
                .map(childNode -> {
                    // 同时使用map方法对每个过滤后的数据进行处理,递归找到其对应的子数据
                    childNode.setChildrenNode(getChildren(childNode, nodes));
                    return childNode;
                })
                .collect(Collectors.toList());
        return childrenNodes;
    }
}

测试:

1)单个父节点模式:http://ip:port/treeNode/oneFather

{
    "id": 1,
    "name": "江西省",
    "pid": 0,
    "childrenNode": [
        {
            "id": 2,
            "name": "吉安市",
            "pid": 1,
            "childrenNode": [
                {
                    "id": 3,
                    "name": "遂川县",
                    "pid": 2,
                    "childrenNode": []
                }
            ]
        },
        {
            "id": 5,
            "name": "赣州市",
            "pid": 1,
            "childrenNode": [
                {
                    "id": 6,
                    "name": "章贡",
                    "pid": 5,
                    "childrenNode": []
                }
            ]
        }
    ]
}

2)多个父节点模式:http://ip:port/treeNode/oneFather

[
    {
        "id": 1,
        "name": "江西省",
        "pid": 0,
        "childrenNode": [
            {
                "id": 2,
                "name": "吉安市",
                "pid": 1,
                "childrenNode": [
                    {
                        "id": 3,
                        "name": "遂川县",
                        "pid": 2,
                        "childrenNode": []
                    }
                ]
            },
            {
                "id": 5,
                "name": "赣州市",
                "pid": 1,
                "childrenNode": [
                    {
                        "id": 6,
                        "name": "章贡",
                        "pid": 5,
                        "childrenNode": []
                    }
                ]
            }
        ]
    },
    {
        "id": 7,
        "name": "浙江省",
        "pid": 0,
        "childrenNode": [
            {
                "id": 8,
                "name": "杭州",
                "pid": 7,
                "childrenNode": []
            }
        ]
    }
]

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,如果要拼接树形结构JSON字符串,可以使用递归的方式来实现。假设我们有一个树形结构数据,每个节点包含一个值和子节点列表。 首先,我们创建一个递归方法,该方法接受一个节点作为参数,并返回一个字符串表示该节点及其子节点的JSON字符串。在方法中,我们首先创建一个StringBuilder对象用于拼接最终的结果。 然后,我们将当前节点的值转换为JSON格式的字符串,并将其添加到StringBuilder对象中。接下来,我们检查当前节点是否有子节点,如果有,则递归调用该方法处理每个子节点,并将结果添加到StringBuilder对象中。 最后,我们在方法的结尾处返回StringBuilder对象的字符串表示形式。 以下是一个示例代码: ``` import com.google.gson.Gson; public class JsonTreeBuilder { public static void main(String[] args) { // 创建树形结构数据 // 构造节点 Node node3 = new Node("Node 3"); Node node4 = new Node("Node 4"); Node node2 = new Node("Node 2", node3, node4); Node node1 = new Node("Node 1", node2); // 将树形结构转换为JSON字符串 String jsonString = buildJsonString(node1); System.out.println(jsonString); } public static String buildJsonString(Node node) { StringBuilder sb = new StringBuilder(); // 添加节点值 sb.append("{ \"value\": \"" + node.getValue() + "\", "); // 添加子节点列表 sb.append("\"children\": ["); for (int i = 0; i < node.getChildren().size(); i++) { sb.append(buildJsonString(node.getChildren().get(i))); if (i < node.getChildren().size() - 1) { sb.append(", "); } } sb.append("] }"); return sb.toString(); } } class Node { private String value; private List<Node> children; public Node(String value, Node... children) { this.value = value; this.children = Arrays.asList(children); } public String getValue() { return value; } public List<Node> getChildren() { return children; } } ``` 上述代码使用了一个Node类来表示树形结构的节点,每个节点包含一个value属性和一个children属性,用于存储子节点列表。在示例代码的main方法中,我们创建了一个树形结构数据,并将其转换为JSON字符串。 在buildJsonString方法中,我们使用StringBuilder对象拼接JSON字符串。首先,我们添加节点的值,并添加一个children属性,然后遍历所有的子节点,并递归调用buildJsonString方法来处理每个子节点。最后,将结果转换为字符串形式并返回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值