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

如何从不完整字符串中提取完整Python可解析对象

从不完整字符串中提取可解析的Python嵌套对象

需求说明

需要从API返回的可能不完整的字符串里,提取能被Python解析的完整字典、列表(包含嵌套结构):

  • 完整字符串如"[{'a' : 1, 'b' : 2}]",需提取整个列表[{'a' : 1, 'b' : 2}];
  • 不完整字符串如"[{'a' : 1, 'b' : 2}, {'a' : 1']",需提取其中完整的字典{'a' : 1, 'b' : 2},并整理为列表[{'a' : 1, 'b' : 2}]。

现有方案的问题

使用正则表达式无法处理嵌套结构——正则不支持递归匹配嵌套的{}/[],遇到多层嵌套时会失效。同时由于字符串不完整,直接用ast.literal_eval会抛出语法错误。

解决方案:基于栈的括号匹配

用栈来跟踪括号的嵌套层级,同时处理引号和转义字符,确保只识别结构层面的括号:

  1. 遍历字符串每个字符,跟踪是否处于引号中(避免误判引号内的括号);
  2. 遇到起始括号{/[时,记录位置并压入栈;
  3. 遇到结束括号}/]时,弹出栈顶的起始括号,若栈为空则说明找到一个完整对象,截取对应区间的字符串;
  4. 最后根据原字符串的格式(如是否以[开头),将提取的对象整理成符合预期的格式。

代码实现

def extract_complete_objects(s):
    stack = []
    start_indices = {}
    complete_objects = []
    in_quote = None  # 标记当前是否处于单/双引号中,值为None、"'"或'"'
    quote_escape = False  # 标记是否遇到转义符

    for idx, char in enumerate(s):
        # 处理转义字符
        if quote_escape:
            quote_escape = False
            continue
        if char == '\\':
            quote_escape = True
            continue
        
        # 处理引号的进入/退出状态
        if char in ("'", '"'):
            if in_quote == char:
                in_quote = None
            elif in_quote is None:
                in_quote = char
            continue
        
        # 处于引号中时,跳过括号处理
        if in_quote is not None:
            continue
        
        # 处理起始括号
        if char in ('{', '['):
            stack.append(char)
            start_indices[len(stack)] = idx
        # 处理结束括号
        elif char in ('}', ']'):
            if not stack:
                continue  # 无匹配的起始括号,直接忽略
            opening_bracket = stack.pop()
            # 检查括号是否匹配
            if (opening_bracket == '{' and char == '}') or (opening_bracket == '[' and char == ']'):
                if not stack:
                    # 栈为空,说明找到一个完整的顶级对象
                    start_idx = start_indices[1]
                    complete_obj = s[start_idx:idx+1]
                    complete_objects.append(complete_obj)
                # 删除当前层级的起始位置记录
                if len(stack) + 1 in start_indices:
                    del start_indices[len(stack) + 1]
    
    # 整理输出格式:如果原字符串以[开头,且提取的是多个独立对象,组合成列表
    if s.strip().startswith('[') and complete_objects:
        if not complete_objects[0].startswith('['):
            return f"[{', '.join(complete_objects)}]"
    # 单个对象直接返回,多个返回列表
    return complete_objects[0] if len(complete_objects) == 1 else complete_objects

测试示例

# 测试完整列表
test1 = "[{'a' : 1, 'b' : 2}]"
print(extract_complete_objects(test1))
# 输出:[{'a' : 1, 'b' : 2}]

# 测试不完整列表
test2 = "[{'a' : 1, 'b' : 2}, {'a' : 1']"
print(extract_complete_objects(test2))
# 输出:[{'a' : 1, 'b' : 2}]

# 测试嵌套不完整列表
test3 = "[[1, 2, 3], [11, 12, 21]"
print(extract_complete_objects(test3))
# 输出:[[1, 2, 3], [11, 12, 21]]

# 测试嵌套字典
test4 = "{'name': 'Alice', 'info': {'age': 30, 'hobbies': ['reading', 'hiking']}, 'address': {"
print(extract_complete_objects(test4))
# 输出:{'name': 'Alice', 'info': {'age': 30, 'hobbies': ['reading', 'hiking']}}

方案优势

  • 完美支持多层嵌套的字典/列表;
  • 正确识别引号内的括号(不会误判为结构括号);
  • 处理转义引号,避免状态错误;
  • 能从任意不完整字符串中提取所有可解析的完整对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:15:44