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

如何将采用2/4空格缩进的文本转换为JSON格式?

缩进文本转JSON的索引错误修复方案

问题背景

我已花费数小时尝试将空格缩进的文本转换为JSON格式。原始文本中,嵌套值采用4空格缩进,键值对采用2空格缩进。编写的Python代码运行时出现索引错误,以下是相关代码、原始数据及期望结果:

尝试代码

import json
from pprint import pprint

lines = raw_text.strip().split('\n')
result = {}
stack = [(0, result)]

for line in lines:
    indent, content = line.split(':', 1)
    indent_level = len(indent) - len(indent.lstrip())
    key = content.strip()
    value = None if key == "null" else {}

    print(indent_level, stack[-1][0])

    while indent_level <= stack[-1][0]:
        stack.pop()

    parent = stack[-1][1] # 此处出现索引错误
    parent[key] = value
    stack.append((indent_level, value))

j = json.dumps(result, indent=4)

原始数据

text = r"""
h0: 
    h1: de8
    h1b: null
    h1c: 
        h2: 
          h3: A
          h3a: S
          h3b: 
              h4: 
                h5: 81
    h1b:
      h1bi: null
      h1bii: null
"""

期望JSON结果

{
    "h0": {
        "h1a": "de8",
        "h1b": "null",
        "h1c": {
            "h2a": {
                "h3a": "A",
                "h3b": "S",
                "h3c": {
                    "h4a": {
                        "h5a": "81"
                    }
                }
            }
        },
        "h1d": {
            "h1di": "null",
            "h1dii": {
                "h2di": "hello",
                "h2dii": "hi"
            }
        }
    }
}

错误原因及修复

核心问题

  • 索引错误触发点:while indent_level <= stack[-1][0]: stack.pop() 会将栈中所有层级大于等于当前缩进的元素弹出,处理最顶层元素时可能把栈弹空,导致stack[-1]报错。
  • 缩进层级计算逻辑错误:代码直接用空格数作为层级,未按原始文本规则(2空格=1层级单位)换算,导致层级判断混乱。
  • 键值处理逻辑缺失:遇到具体文本值(如de8)时错误设为{};原始文本重复键(h1b)会被直接覆盖。
  • 变量名不匹配:代码使用raw_text但原始数据变量是text,存在引用错误。

修复后的代码

import json

# 统一输入变量名
raw_text = r"""
h0: 
    h1: de8
    h1b: null
    h1c: 
        h2: 
          h3: A
          h3a: S
          h3b: 
              h4: 
                h5: 81
    h1b:
      h1bi: null
      h1bii: null
"""

lines = raw_text.strip().split('\n')
result = {}
# 初始化栈,存储(层级, 对应字典)
stack = [(0, result)]

for line in lines:
    if ':' not in line:
        continue
    indent_part, content = line.split(':', 1)
    # 按2空格为1层级转换缩进数
    indent_spaces = len(indent_part) - len(indent_part.lstrip())
    indent_level = indent_spaces // 2
    key = content.strip()
    
    # 区分值类型:null/空内容/具体文本
    if key == "null":
        value = None
    elif not key:
        value = {}
    else:
        value = key

    # 仅弹出层级高于当前的栈元素,保留父节点
    while stack[-1][0] > indent_level:
        stack.pop()
    
    parent = stack[-1][1]
    # 处理重复键,添加数字后缀避免覆盖
    if key in parent:
        suffix = 1
        while f"{key}{suffix}" in parent:
            suffix += 1
        key = f"{key}{suffix}"
    parent[key] = value
    
    # 仅字典类型入栈,用于后续嵌套
    if isinstance(value, dict):
        stack.append((indent_level + 1, value))

# 生成格式化JSON
j = json.dumps(result, indent=4)
print(j)

修复说明

  • 缩进标准化:将缩进空格数除以2,统一为层级单位,匹配原始文本2空格键值对、4空格嵌套的规则。
  • 栈逻辑修正:调整弹出条件为stack[-1][0] > indent_level,避免弹空栈,同时保证父节点正确。
  • 值处理完善:区分空内容(生成字典)、null(生成None)、具体文本值(生成字符串)三种情况。
  • 重复键处理:为重复键添加数字后缀,保留所有原始数据。
  • 变量名统一:修正输入变量名不一致的问题,保证代码可直接运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:57:38