解析TestRail API getcases响应JSON,梳理父子ID层级关系
Hey there! Let's break down how to parse that flat JSON list from TestRail's getcases endpoint into a clear hierarchical structure—showing each top-level parent ID (where parent_id is null) and all of its nested child IDs across every level.
核心思路
First, we'll build a quick lookup map to link each parent ID directly to its immediate children. Then, we'll recursively (or iteratively) traverse this map to collect all descendants for each top-level parent.
示例实现(Python)
Let's use your sample JSON to demonstrate:
1. 定义原始数据
testrail_cases = [ {"id": 1, "parent_id": None}, {"id": 2, "parent_id": 1}, {"id": 6, "parent_id": None}, {"id": 16, "parent_id": 2}, {"id": 7, "parent_id": 1}, {"id": 3, "parent_id": 6} ]
2. 构建父-子映射表
This step creates an O(1) lookup for any parent's direct children:
parent_map = {} for case in testrail_cases: parent_id = case["parent_id"] case_id = case["id"] # Initialize empty list if parent isn't in the map yet if parent_id not in parent_map: parent_map[parent_id] = [] parent_map[parent_id].append(case_id)
3. 递归收集所有层级的子节点
This function will dive through every nested level to gather all descendants of a given parent:
def get_all_descendants(parent_id): descendants = [] # Check if the parent has direct children if parent_id in parent_map: for child_id in parent_map[parent_id]: descendants.append(child_id) # Recursively add the child's own descendants descendants.extend(get_all_descendants(child_id)) return descendants
4. 生成最终的层级归属结果
We'll target only top-level parents (where parent_id is None):
hierarchical_result = {} # Iterate over all top-level parent IDs for top_parent_id in parent_map.get(None, []): hierarchical_result[top_parent_id] = get_all_descendants(top_parent_id) # Print the result print(hierarchical_result)
输出结果
{1: [2, 16, 7], 6: [3]}
This means:
- Top-level parent
1has nested children:2(which has child16), and7 - Top-level parent
6has direct child3
可选:迭代版(避免递归栈溢出)
If you're dealing with extremely deep hierarchies, use an iterative approach instead:
def get_all_descendants_iterative(parent_id): descendants = [] stack = [parent_id] while stack: current_id = stack.pop() # Add all direct children of current ID for child_id in parent_map.get(current_id, []): descendants.append(child_id) stack.append(child_id) return descendants
为什么这个方法好用?
- Efficiency: The initial map build is O(n), and collecting descendants is also O(n) (each case is processed once)
- Scalability: Works for any number of nested levels from TestRail's API
- Clarity: The result directly maps each top-level parent to every ID under its hierarchy
内容的提问来源于stack exchange,提问作者Mahyar

