Python中如何将OrderedDict格式字符串安全转换为JSON
解决方案
实现思路
- 安全解析使用
ast.literal_eval:该函数仅支持解析Python字面量结构(字典、列表、元组、字符串、数字等),不会执行任意代码,完全规避eval的安全风险 - 解析时将
OrderedDict注册到解析上下文,让解析器可以识别输入中的OrderedDict结构 - 递归遍历解析后的Python对象,统一处理特殊类型:将bytes类型的键/值转为UTF-8编码的字符串、u前缀的unicode字符串直接转为普通字符串、所有OrderedDict实例转为普通dict
- 最后可直接输出Python对象,或调用
json.dumps输出JSON格式结果
完整实现代码
import ast import json from collections import OrderedDict def parse_struct_string(input_str: str): # 安全解析输入字符串为Python对象 parsed_obj = ast.literal_eval(input_str, globals={'OrderedDict': OrderedDict}) # 递归转换特殊类型 def _convert(node): # 处理字典/OrderedDict类型 if isinstance(node, (dict, OrderedDict)): res = {} for k, v in node.items(): # 处理键的特殊类型 if isinstance(k, bytes): new_k = k.decode('utf-8') elif isinstance(k, str): new_k = str(k) else: new_k = k res[new_k] = _convert(v) return res # 处理列表/元组类型 elif isinstance(node, (list, tuple)): return [_convert(item) for item in node] # 处理bytes类型的值 elif isinstance(node, bytes): return node.decode('utf-8') # 其他类型直接返回 else: return node return _convert(parsed_obj) # 直接输出JSON的封装方法 def struct_to_json(input_str: str, **json_kwargs) -> str: parsed_data = parse_struct_string(input_str) return json.dumps(parsed_data, **json_kwargs)
场景验证
所有题目中给出的场景均可正常运行:
- 单个OrderedDict格式字符串
input_str = "OrderedDict({'abc': 1})" print(parse_struct_string(input_str)) # 输出: {'abc': 1}
- 递归嵌套的OrderedDict格式字符串
input_str = "OrderedDict([('abc', OrderedDict([('def', 2)]))])" print(parse_struct_string(input_str)) # 输出: {'abc': {'def': 2}}
- 包含OrderedDict值的字典格式字符串
input_str = "{'key': OrderedDict([('abc', 1)])}" print(parse_struct_string(input_str)) # 输出: {'key': {'abc': 1}}
- 包含OrderedDict值的列表格式字符串
input_str = "[OrderedDict([('abc', 1)])]" print(parse_struct_string(input_str)) # 输出: [{'abc': 1}]
- 普通字典格式字符串
input_str = "{'abc': 1}" print(parse_struct_string(input_str)) # 输出: {'abc': 1}
- 普通列表格式字符串
input_str = "[{'abc': 1}]" print(parse_struct_string(input_str)) # 输出: [{'abc': 1}]
- 包含unicode或bytes类型键的字符串
input_str = "{u'abc': 1}" print(parse_struct_string(input_str)) # 输出: {'abc': 1} input_str = "{b'abc': 1}" print(parse_struct_string(input_str)) # 输出: {'abc': 1}
注意事项
- 若bytes类型的编码不是UTF-8,可自行修改
decode方法的编码参数,也可添加errors='ignore'忽略解码异常字符 - 若需要保留OrderedDict的插入顺序,仅需在递归转换时不将其转为普通dict,
json.dumps默认会按OrderedDict的顺序输出
内容的提问来源于stack exchange,提问作者binpy
相关产品推荐
相关产品推荐

