如何在Python中遍历嵌套YAML文档并构建指定结构对象?
遍历嵌套YAML并生成指定结构的对象列表
问题背景
现有如下嵌套结构的YAML文件,需要遍历并生成包含RuleName、IgnoreList<LIST>、InputParameters<LIST>、RuleType、SubRuleType属性的对象列表:
--- InternalRuleService: - HomeRules: - RuleName: Sample1 IgnoreList: InputParameters: - resourceId: some-res-id - ruleAge: 1 - ruleAgeUnits: days - RuleName: Sample2 IgnoreList: - Account: '12' Region: NorthAmericas - Account: '10' Region: AsiaPacific - Account: '10' Region: Europe InputParameters: - InterfaceIds: xxxx1,xxxxx2 - RuleName: Sample3 IgnoreList: - Account: '14' Region: NorthAmericas - Account: '18' Region: MiddleEast InputParameters: - localContact: JohnDoe contactNumber: 123123 - CustomRules: - RuleName: CustomOne documentType: packet IgnoreList: - Account: '14' Region: NorthAmericas - Account: '18' Region: MiddleEast ThirdPartyRules: - RuleName: alta-prism licenseType: multi licenseAge: 5 licenseAgeUnit: year IgnoreList: - Account: '45' Region: NorthAmericas - Account: '44' Region: MiddleEast
之前尝试的代码仅能输出顶层键,访问子元素时出现错误:
import yaml import json with open('rules.yml', 'r') as file: rules = yaml.safe_load(file) for rows in rules: print(rows)
输出仅为InternalRuleService和ThirdPartyRules。
尝试访问HomeRules时:
for rows in rules: print(rows['HomeRules'])
报错:
TypeError: string indices must be integers
使用索引访问时:
for rows in rules: print(rows[0])
仅输出字符I和T。
解决方案
错误原因分析
遍历rules(字典对象)时,默认迭代的是字典的键(字符串类型),而非键对应的值,因此直接对字符串使用字典索引或列表索引会报错。需要遍历字典的键值对,逐层解析嵌套结构。
正确代码实现
以下代码会逐层遍历YAML结构,生成符合要求的对象列表(这里用字典存储每个对象,也可根据需求自定义类):
import yaml def parse_rules(yaml_file_path): result = [] with open(yaml_file_path, 'r') as file: rules = yaml.safe_load(file) # 遍历顶层规则类型(InternalRuleService/ThirdPartyRules) for rule_type, rule_data in rules.items(): if rule_type == 'InternalRuleService': # 处理内部规则,包含HomeRules/CustomRules子类型 for sub_rule_group in rule_data: # 每个子规则组是只有一个键值对的字典(HomeRules或CustomRules) sub_rule_type, rule_list = next(iter(sub_rule_group.items())) for rule in rule_list: # 构建对象,补全默认空列表 rule_obj = { 'RuleName': rule.get('RuleName'), 'IgnoreList': rule.get('IgnoreList', []), 'InputParameters': rule.get('InputParameters', []), 'RuleType': rule_type, 'SubRuleType': sub_rule_type } result.append(rule_obj) elif rule_type == 'ThirdPartyRules': # 处理第三方规则,无SubRuleType for rule in rule_data: rule_obj = { 'RuleName': rule.get('RuleName'), 'IgnoreList': rule.get('IgnoreList', []), 'InputParameters': rule.get('InputParameters', []), 'RuleType': rule_type, 'SubRuleType': None # 第三方规则无SubRuleType } result.append(rule_obj) return result # 调用示例 if __name__ == '__main__': parsed_rules = parse_rules('rules.yml') # 打印结果验证 for idx, obj in enumerate(parsed_rules): print(f"对象 {idx+1}:") print(obj) print('---')
代码说明
- 遍历顶层键值对:使用
rules.items()获取规则类型(键)和对应的数据(值),而非仅遍历键。 - 区分规则类型:
- 对于
InternalRuleService,其值是一个列表,每个元素是包含HomeRules或CustomRules的字典,通过next(iter(sub_rule_group.items()))取出子规则类型和对应的规则列表。 - 对于
ThirdPartyRules,其值直接是规则列表,无需处理子类型。
- 对于
- 补全默认值:使用
dict.get()方法获取属性,当YAML中未定义IgnoreList或InputParameters时,默认返回空列表,避免出现None。 - 构建对象:按照需求组装每个规则对象,添加
RuleType和SubRuleType属性。
输出示例
运行代码后,会生成如下结构的对象列表(示例部分输出):
对象 1: {'RuleName': 'Sample1', 'IgnoreList': [], 'InputParameters': [{'resourceId': 'some-res-id'}, {'ruleAge': 1}, {'ruleAgeUnits': 'days'}], 'RuleType': 'InternalRuleService', 'SubRuleType': 'HomeRules'} --- 对象 2: {'RuleName': 'Sample2', 'IgnoreList': [{'Account': '12', 'Region': 'NorthAmericas'}, {'Account': '10', 'Region': 'AsiaPacific'}, {'Account': '10', 'Region': 'Europe'}], 'InputParameters': [{'InterfaceIds': 'xxxx1,xxxxx2'}], 'RuleType': 'InternalRuleService', 'SubRuleType': 'HomeRules'} --- 对象 5: {'RuleName': 'alta-prism', 'IgnoreList': [{'Account': '45', 'Region': 'NorthAmericas'}, {'Account': '44', 'Region': 'MiddleEast'}], 'InputParameters': [], 'RuleType': 'ThirdPartyRules', 'SubRuleType': None} ---
内容的提问来源于stack exchange,提问作者user20358
相关产品推荐
相关产品推荐

