通八洲科技

Python JSON生成时字符串被意外包裹为列表的根源与修复方案

日期:2026-01-02 00:00 / 作者:聖光之護

问题源于python中无意添加的尾随逗号,导致赋值语句创建了单元素元组(如 `x = "val",`),而`json.dumps()`会将元组序列化为json数组,造成`"key": ["value"]`的异常输出。

在您提供的代码中,核心错误隐藏在构建 entry 字典的赋值语句末尾——多处使用了不必要的尾随逗号(,),这在Python中会将右侧表达式强制转为单元素元组。例如:

entry["itemId"] = gen_id(),   # ❌ 错误:尾随逗号 → 创建元组 ('uuid-string',)
entry["date"] = gen_date_string(),  # ❌ 同样 → ('2011-08-11 22:41:09',)
entry["size"] = {"width": ..., "height": ..., "depth": ...},  # ❌ 元组包含一个字典!

由于 json.dumps() 在序列化时会将 Python 元组(tuple)统一转换为 JSON 数组(array),因此所有带尾随逗号的字段(itemId, date, subjectAreas, title, description, method, materials, size 等)均被包裹成长度为1的数组,如 "itemId": ["42198f4d-..."],而非预期的字符串 "itemId": "42198f4d-..."。

正确写法是彻底移除所有赋值语句末尾的逗号

for num in range(0, 2):
    entry = entry_template.copy()
    entry["itemId"] = gen_id()                    # ✅ 无逗号
    entry["date"] = gen_date_string()             # ✅ 无逗号
    entry["subjectAreas"] = select_val(subjectAreas)  # ✅ 注意:subjectAreas本身是字符串列表(如 ["drawings"]),此赋值正确
    entry["images"] = gen_image_ids()           # ✅ gen_image_ids() 已返回 list,无需改动
    entry["title"] = select_val(titles)         # ✅ 返回 str,正确
    entry["description"] = select_val(descriptions)  # ✅ 返回 str
    entry["method"] = select_val(methods)
    entry["materials"] = select_val(materials)
    entry["size"] = {                           # ✅ 字典字面量,结尾无逗号(除非多行且需PEP8兼容)
        "width": gen_dimension(),
        "height": gen_dimension(),
        "depth": gen_dimension()
    }
    entry["weight"] = gen_dimension()           # ✅
    entries.append(entry)

? 快速排查技巧
运行前可临时打印 type(entry["itemId"]) 和 repr(entry["itemId"]),若输出 和 ('xxx',),即确认存在尾随逗号问题。

⚠️ 额外注意点

立即学习“Python免费学习笔记(深入)”;

修复后,json.dumps(entries, indent=4) 将生成符合前端JavaScript消费标准的纯净JSON结构:字符串保持为字符串,数字为数字,列表为数组,嵌套对象为对象——完全匹配您期望的手动编辑格式。