You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python:通过loads()加载JSON字符串时无法解析内嵌字典项

解决方案

方案1:用AST+受限命名空间安全求值

eval()的安全风险在于它会执行任意代码,而通过ast模块解析表达式并在受限命名空间中执行,可以避免这个问题——只传入你允许访问的变量,且禁用所有内置函数。

示例代码:

import ast

# 你的目标字典
target_dict = {"product": "Laptop", "price": 999}

# 从文本文件读取的参数引用字符串
param_ref = "target_dict['product']"

# 将字符串解析为AST表达式树
expr_tree = ast.parse(param_ref, mode='eval')
# 在受限环境中执行:仅传入允许的变量,禁用内置函数
result = eval(
    compile(expr_tree, filename='', mode='eval'),
    {"__builtins__": None},  # 禁用所有内置函数,防止恶意调用
    {"target_dict": target_dict}  # 只暴露需要访问的字典
)

print(result)  # 输出: Laptop

这个方法允许支持Python风格的字典引用,但严格限制了可访问的变量范围,不会执行恶意代码。

方案2:自定义参数标记与解析规则

如果可以调整文本文件的参数格式,用自定义标记(比如{{dict.key}})来表示字典项,然后自己实现解析逻辑,完全避免代码执行风险。

示例实现:

import re

def resolve_dict_refs(param_str, allowed_dicts):
    """解析带自定义标记的参数字符串,替换为字典实际值"""
    def replace_match(match):
        ref_expr = match.group(1)
        # 拆分引用路径,支持 dict['key'] 或 dict.key 格式
        parts = ref_expr.split('.')
        current = allowed_dicts
        for part in parts:
            # 处理带引号的键(如 'product')
            if part.startswith(("'", '"')) and part.endswith(("'", '"')):
                key = part[1:-1]
                current = current[key]
            else:
                current = current[part]
        return str(current)
    
    # 匹配 {{dict_ref}} 格式的标记
    return re.sub(r'\{\{([^}]+)\}\}', replace_match, param_str)

# 使用示例
my_dict = {"product": "Laptop", "price": 999}
text_param = "商品名称:{{my_dict['product']}},价格:{{my_dict.price}}"
resolved_param = resolve_dict_refs(text_param, {"my_dict": my_dict})

print(resolved_param)  # 输出: 商品名称:Laptop,价格:999

这个方案最可控,完全由你定义解析规则,不存在代码执行的安全隐患,适合对安全性要求高的场景。

方案3:改用支持引用的安全配置格式

如果文本文件可以改为更规范的配置格式(如YAML),可以利用格式本身的引用机制,配合安全加载器实现需求。

比如用YAML自定义标签实现字典键引用:

import yaml

# 自定义YAML标签处理器,解析 !ref 标签
def ref_constructor(loader, node):
    ref_path = loader.construct_scalar(node)
    parts = ref_path.split('.')
    current = loader.construct_mapping(loader.nodes[0], deep=True)
    for part in parts:
        if part.startswith(("'", '"')) and part.endswith(("'", '"')):
            key = part[1:-1]
            current = current[key]
        else:
            current = current[part]
    return current

yaml.add_constructor('!ref', ref_constructor)

# 配置文件内容示例
config_content = """
my_dict:
  product: Laptop
  price: 999
function_params:
  name: !ref my_dict.product
  cost: !ref my_dict['price']
"""

# 安全加载配置
config = yaml.safe_load(config_content)
print(config['function_params']['name'])  # 输出: Laptop

这个方案适合需要复杂配置的场景,依赖成熟的配置解析库,安全性更高。


内容的提问来源于stack exchange,提问作者theZeigs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:23:18