json数据获取当前id的所有父级id,并排序

本文介绍了一种处理城市信息JSON数据的方法,通过递归函数获取指定ID的父级ID列表,并进行排序,以便于管理和查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我做的是一个城市信息json数据

json数据类型:
![在这里插入图片描述](https://img-blog.csdnimg.cn/2018121210581941.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4NzYxNTkz,size_16,color_FFFFFF,t_70)
//获取方法
fordata(pid){
      	     var pdata = this.$data.pidarrdata;
      	     var arr = [];
            for (var i in pdata) {
                if (pdata[i].id == pid) {
					if(pdata[i].pid == 0){
						//GetParentId(s[i].pid)
					}else{
						arr.push(pdata[i].pid);
						arr = arr.concat(this.fordata(pdata[i].pid));
					}
                }
			} 
            return arr;

      	},
      	//排序
      	var pid = [data.pid]
      		pid = pid.concat(this.fordata(data.pid));
      		var newpid = pid.sort(function (x,y) {
	            return x-y;
	        });
<think>我们需要构建一个树形结构的JSON数据,通常职业数据有层关系(例如:职业分类->具体职业)。假设我们有一个职业分类表,表结构如下: 表:occupation 字段: id: 主键 name: 职业名称 parent_id: ID,顶分类的parent_id为0或null 目标:查询数据库,构建一个树形结构的JSON,例如: [ { "id": 1, "name": "IT", "children": [ { "id": 2, "name": "软件开发", "children": [ {"id": 3, "name": "Java开发", "children": []}, {"id": 4, "name": "Python开发", "children": []} ] } ] }, ... ] 步骤: 1. 从数据库查询所有职业数据(一次性查询,避免多次查询数据库) 2. 在内存中构建树形结构 3. 将树形结构转换为JSON 注意:如果数据量很大,需要考虑递归深度和性能(使用非递归方式构建树) 以下使用MyBatis Plus和Spring Boot为例,但核心逻辑是通用的。 首先,定义实体类: */ // Occupation.java /* public class Occupation { private Long id; private String name; private Long parentId; // 省略getter/setter } */ // 构建树形结构的工具类 /* import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; public class TreeBuilder { // 构建树形结构 public static List<OccupationNode> buildTree(List<Occupation> occupations) { // 先用一个Map来存储id和节点的映射关系,同时将原始数据转换为节点 Map<Long, OccupationNode> nodeMap = new HashMap<>(); List<OccupationNode> nodes = new ArrayList<>(); // 第一步:将每个Occupation转换为OccupationNode,放入map和list for (Occupation occupation : occupations) { OccupationNode node = new OccupationNode(); node.setId(occupation.getId()); node.setName(occupation.getName()); node.setChildren(new ArrayList<>()); nodeMap.put(occupation.getId(), node); nodes.add(node); } // 第二步:构建树 List<OccupationNode> rootNodes = new ArrayList<>(); for (OccupationNode node : nodes) { // 查找当前节点的节点 Long parentId = occupations.stream() .filter(occ -> occ.getId().equals(node.getId())) .findFirst() .map(Occupation::getParentId) .orElse(null); // 如果parentId为0或null,则为根节点 if (parentId == null || parentId == 0) { rootNodes.add(node); } else { // 找到节点,将当前节点加入节点的children OccupationNode parentNode = nodeMap.get(parentId); if (parentNode != null) { parentNode.getChildren().add(node); } } } return rootNodes; } } // 树形节点类 public class OccupationNode { private Long id; private String name; private List<OccupationNode> children; // 省略getter/setter } */ // 在Controller中调用 /* @RestController @RequestMapping("/occupation") public class OccupationController { @Autowired private OccupationService occupationService; @GetMapping("/tree") public List<OccupationNode> getOccupationTree() { // 查询所有职业数据 List<Occupation> occupations = occupationService.listAll(); // 构建树 return TreeBuilder.buildTree(occupations); } } */ // 但是,上面的方法在构建树时假设了parentId不为0或null的节点都有节点(在nodeMap中)。如果数据有误(比如parentId指向了一个不存在的节点),则这些节点会被忽略(成为游离节点,不会被加入树中)。如果需要将这些游离节点也作为根节点,可以修改构建逻辑。 // 优化:使用递归方式(但数据量大时递归可能栈溢出,且效率不高)所以这里使用非递归。 // 另一种构建树的方法(使用Stream API): /* public static List<OccupationNode> buildTreeByStream(List<Occupation> occupations) { // 先按parentId分组 Map<Long, List<Occupation>> groupByParentId = occupations.stream() .collect(Collectors.groupingBy(Occupation::getParentId)); // 创建节点映射 Map<Long, OccupationNode> nodeMap = new HashMap<>(); occupations.forEach(occ -> { OccupationNode node = new OccupationNode(); node.setId(occ.getId()); node.setName(occ.getName()); node.setChildren(new ArrayList<>()); nodeMap.put(occ.getId(), node); }); // 构建树 List<OccupationNode> rootNodes = new ArrayList<>(); occupations.forEach(occ -> { Long parentId = occ.getParentId(); if (parentId == null || parentId == 0) { rootNodes.add(nodeMap.get(occ.getId())); } else { OccupationNode parentNode = nodeMap.get(parentId); if (parentNode != null) { parentNode.getChildren().add(nodeMap.get(occ.getId())); } } }); // 排序(如果需要) // ... return rootNodes; } */ // 注意:以上两种方法都是O(n)复杂度,效率较高。 // 如果使用递归构建树(不推荐大数据量,但代码简洁): /* public static List<OccupationNode> buildTreeRecursive(List<Occupation> occupations) { // 先获取所有根节点(parentId为0或null) List<Occupation> roots = occupations.stream() .filter(occ -> occ.getParentId() == null || occ.getParentId() == 0) .collect(Collectors.toList()); return roots.stream().map(root -> { OccupationNode rootNode = new OccupationNode(); rootNode.setId(root.getId()); rootNode.setName(root.getName()); rootNode.setChildren(getChildren(root, occupations)); return rootNode; }).collect(Collectors.toList()); } private static List<OccupationNode> getChildren(Occupation parent, List<Occupation> occupations) { List<Occupation> children = occupations.stream() .filter(occ -> parent.getId().equals(occ.getParentId())) .collect(Collectors.toList()); if (children.isEmpty()) { return new ArrayList<>(); } return children.stream().map(child -> { OccupationNode childNode = new OccupationNode(); childNode.setId(child.getId()); childNode.setName(child.getName()); childNode.setChildren(getChildren(child, occupations)); return childNode; }).collect(Collectors.toList()); } */ // 实际项目中,推荐非递归方式(避免栈溢出,性能更好)。 // 最终,返回的JSON就是树形结构。 // 示例:使用MyBatis Plus查询所有数据 /* @Service public class OccupationServiceImpl extends ServiceImpl<OccupationMapper, Occupation> implements OccupationService { @Override public List<Occupation> listAll() { return baseMapper.selectList(null); // 查询所有 } } */ // 注意:如果数据量很大(比如几十万条),一次性查询所有数据构建树可能内存占用高,此时需要分页或懒加载树。但本问题假设数据量不大。 // 完整代码示例(使用非递归方式):</think># Java查询职业数据以树形JSON返回前端 我将提供一个完整的解决方案,用于从数据库中查询职业数据以树形JSON格式返回给前端。这种结构特别适合展示层关系(如职业分类体系)。 ## 解决方案 ### 数据结构设计 假设我们有以下职业分类表结构: ```sql CREATE TABLE occupations ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, parent_id INT DEFAULT NULL, description VARCHAR(255), level INT DEFAULT 1, FOREIGN KEY (parent_id) REFERENCES occupations(id) ); ``` ### Java实现代码 ```java import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import java.sql.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class OccupationTreeBuilder { // 职业节点类 @Data @JsonInclude(JsonInclude.Include.NON_EMPTY) static class OccupationNode { private int id; private String name; private String description; private int level; private List<OccupationNode> children = new ArrayList<>(); public OccupationNode(int id, String name, String description, int level) { this.id = id; this.name = name; this.description = description; this.level = level; } } // 数据库连接信息 private static final String DB_URL = "jdbc:mysql://localhost:3306/career_db"; private static final String DB_USER = "username"; private static final String DB_PASSWORD = "password"; public static void main(String[] args) { // 1. 从数据获取所有职业数据 List<OccupationNode> allOccupations = fetchOccupationsFromDB(); // 2. 构建职业树 List<OccupationNode> occupationTree = buildOccupationTree(allOccupations); // 3. 转换为JSON String jsonResult = convertToJson(occupationTree); System.out.println("树形JSON结果:"); System.out.println(jsonResult); } // 从数据获取所有职业 private static List<OccupationNode> fetchOccupationsFromDB() { List<OccupationNode> occupations = new ArrayList<>(); String query = "SELECT id, name, description, level FROM occupations ORDER BY level, name"; try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query)) { while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); String description = rs.getString("description"); int level = rs.getInt("level"); occupations.add(new OccupationNode(id, name, description, level)); } } catch (SQLException e) { e.printStackTrace(); } return occupations; } // 构建职业树 private static List<OccupationNode> buildOccupationTree(List<OccupationNode> occupations) { // 创建节点映射表 Map<Integer, OccupationNode> nodeMap = new HashMap<>(); List<OccupationNode> rootNodes = new ArrayList<>(); // 第一遍:将所有节点放入映射表 for (OccupationNode node : occupations) { nodeMap.put(node.getId(), node); } // 第二遍:构建树结构 for (OccupationNode node : occupations) { // 获取节点ID int parentId = getParentId(node.getId()); // 这里需要实现获取节点ID的方法 if (parentId == 0) { // 根节点 rootNodes.add(node); } else { OccupationNode parent = nodeMap.get(parentId); if (parent != null) { parent.getChildren().add(node); } } } return rootNodes; } // 实际应用中应从数据获取ID,这里简化实现 private static int getParentId(int id) { // 实际项目中应查询数据获取ID // 这里仅作为示例,返回一个简化逻辑 if (id > 100) return id / 10; // 假设ID当前ID除以10 return 0; // 0表示根节点 } // 转换为JSON字符串 private static String convertToJson(List<OccupationNode> tree) { try { ObjectMapper mapper = new ObjectMapper(); return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(tree); } catch (JsonProcessingException e) { e.printStackTrace(); return "{}"; } } } ``` ### 代码说明 1. **数据结构**: - `OccupationNode` 类表示职业节点,包含基本信息和子节点列表 - 使用 `@JsonInclude(JsonInclude.Include.NON_EMPTY)` 注解确保空子节点列表不输出 2. **数据库操作**: - 使用JDBC连接数据查询所有职业数据 - 按层和名称排序,确保节点在子节点之前 3. **树形结构构建**: - 使用两次遍历构建树:第一次创建节点映射,第二次建立子关系 - 根节点的ID为0(或null) 4. **JSON转换**: - 使用Jackson库将Java对象转换为格式化的JSON - 使用`writerWithDefaultPrettyPrinter()`实现美观的输出格式 ### 示例JSON输出 ```json [ { "id": 1, "name": "信息技术", "description": "IT相关职业", "level": 1, "children": [ { "id": 11, "name": "软件开发", "description": "软件开发相关职位", "level": 2, "children": [ { "id": 111, "name": "前端开发", "description": "Web前端开发", "level": 3 }, { "id": 112, "name": "后端开发", "description": "服务器端开发", "level": 3 } ] }, { "id": 12, "name": "数据科学", "description": "数据分析与处理", "level": 2, "children": [ { "id": 121, "name": "数据分析师", "description": "业务数据分析", "level": 3 } ] } ] }, { "id": 2, "name": "医疗健康", "description": "医疗相关职业", "level": 1, "children": [ { "id": 21, "name": "医生", "description": "临床医生", "level": 2 } ] } ] ``` ## 优化建议 1. **数据库查询优化**: ```java // 使用预编译语句提高性能 String query = "SELECT id, name, description, level, parent_id FROM occupations"; ``` 2. **递归构建树**(适合不确定深度的情况): ```java private static void buildTreeRecursive(OccupationNode parent, Map<Integer, List<OccupationNode>> parentMap) { List<OccupationNode> children = parentMap.get(parent.getId()); if (children != null) { for (OccupationNode child : children) { parent.getChildren().add(child); buildTreeRecursive(child, parentMap); } } } ``` 3. **添加缓存**: ```java // 使用Guava Cache或Caffeine缓存树形结构 LoadingCache<String, List<OccupationNode>> occupationTreeCache = Caffeine.newBuilder() .expireAfterWrite(1, TimeUnit.HOURS) .build(key -> buildOccupationTree(fetchOccupationsFromDB())); ``` 4. **分页加载**(适合大数据量): ```java public List<OccupationNode> getOccupationTree(int parentId, int page, int size) { // 查询指定ID的子节点 String query = "SELECT * FROM occupations WHERE parent_id = ? LIMIT ? OFFSET ?"; // ... } ``` ## 相关技术栈 - **数据库**:MySQL/PostgreSQL - **JDBC**:Java数据库连接 - **Jackson**:JSON处理库 - **Lombok**:简化POJO代码 - **连接池**:HikariCP或Druid
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_28761593

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值