diff --git a/README.md b/README.md index 0d427be..34b8de9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ ### TODO: +- [X] 宽容的json验证,支持data:list:[]这样 +- [ ] 对接dms系统 - [ ] 针对assets/doc/接口返回.txt 的parser的编写 - [ ] 针对assets/images/井筒/后端开发指南.txt的测试用例 -[昆仑文档链接](https://nipj5983sr.fklzl.cnpc.com.cn/wiki/C287wqYvdiMdehk8Kp6gcPtPt7f) + [昆仑文档链接](https://nipj5983sr.fklzl.cnpc.com.cn/wiki/C287wqYvdiMdehk8Kp6gcPtPt7f) - [ ] 针对assets/images/井筒/DMS增加核心服务api.txt的测试用例 -[昆仑文档链接](https://nipj5983sr.fklzl.cnpc.com.cn/wiki/IDQowkL45iq1FrkrPtngdQKEtyb) + [昆仑文档链接](https://nipj5983sr.fklzl.cnpc.com.cn/wiki/IDQowkL45iq1FrkrPtngdQKEtyb) - [ ] 增加机制,吧schema和响应列给大模型+用户prompt,实现自定义测试用例(可选) - [ ] 修改前端,改为查看测试历史记录的报告与管理测试用例 @@ -23,5 +25,3 @@ make run_stages ### 开发 cursor-memory-bank在memory-bank目录下,对话前先传给cursor或其他ai - - diff --git a/ddms_compliance_suite/utils/response_utils.py b/ddms_compliance_suite/utils/response_utils.py index de6189c..ff4ea1e 100644 --- a/ddms_compliance_suite/utils/response_utils.py +++ b/ddms_compliance_suite/utils/response_utils.py @@ -1,19 +1,23 @@ -from typing import Any, List +from typing import Any, List, Optional import logging logger = logging.getLogger(__name__) -def extract_data_for_validation(response_json: Any) -> List[Any]: +def extract_data_for_validation(response_json: Any, nested_list_keywords: Optional[List[str]] = None) -> List[Any]: """ 从原始API响应JSON中智能提取需要被验证的核心业务数据列表。 即使只有一个对象,也返回一个单元素的列表。 策略: 1. 如果响应体是包含 'code' 和 'data' 的标准包装,则提取 'data' 的内容。 - 2. 如果处理后的数据是列表,直接返回该列表。 - 3. 如果处理后的数据是单个对象(字典),将其包装在单元素列表中返回。 - 4. 如果数据为空或不适用,返回空列表。 + 2. 对上一步的结果,遍历一个关键字列表(nested_list_keywords),检查是否存在分页列表模式,如果存在则提取该列表。 + 3. 如果处理后的数据是列表,直接返回该列表。 + 4. 如果处理后的数据是单个对象(字典),将其包装在单元素列表中返回。 + 5. 如果数据为空或不适用,返回空列表。 """ + if nested_list_keywords is None: + nested_list_keywords = ["list", "records", "items", "data"] + if not response_json: return [] @@ -24,7 +28,15 @@ def extract_data_for_validation(response_json: Any) -> List[Any]: logger.debug("检测到标准响应包装,提取 'data' 字段内容进行处理。") data_to_process = response_json['data'] - # 策略 2: 统一返回列表 + # 策略 2: 提取嵌套的分页列表 + if isinstance(data_to_process, dict): + for keyword in nested_list_keywords: + if keyword in data_to_process and isinstance(data_to_process[keyword], list): + logger.debug(f"检测到关键字为 '{keyword}' 的嵌套列表,提取其内容。") + data_to_process = data_to_process[keyword] + break # 找到第一个匹配的就停止 + + # 策略 3 & 4: 统一返回列表 if isinstance(data_to_process, list): logger.debug(f"数据本身为列表,包含 {len(data_to_process)} 个元素,直接返回。") return data_to_process @@ -33,6 +45,6 @@ def extract_data_for_validation(response_json: Any) -> List[Any]: logger.debug("数据为单个对象,将其包装在列表中返回。") return [data_to_process] - # 对于其他情况(如数据为None或非对象/列表类型),返回空列表 + # 策略 5: 对于其他情况(如数据为None或非对象/列表类型),返回空列表 logger.warning(f"待处理的数据既不是列表也不是对象,无法提取进行验证。数据: {str(data_to_process)[:100]}") return [] \ No newline at end of file