别再直接 `json.loads` 了!AI 返回的 JSON 坑位指南

01. 成就感背后的"生产事故"

当你第一次成功让模型返回一个完美的 JSON 结构时,那种"代码终于受控"的成就感溢于言表。但如果你直接在代码里写下 print(data['title']),那么恭喜你,你已经为未来的生产事故埋下了伏笔。

在 AI 工程中,有一个残酷的现实:模型返回 JSON,并不代表程序可以无条件信任它。


02. 模型会给 JSON 挖哪些坑?

即便你用了最强的 GPT-4 或 Claude 3,模型依然会偶尔"掉链子"。常见的异常场景包括:

1. 结构性"幻觉"

你要求返回一个数组,模型可能因为上下文太长,返回了一个被截断的字符串,或者干脆在 JSON 前后加了句"这是你要的结果:"。

  • 后果json.loads() 直接抛出 ValueErrorJSONDecodeError

2. 字段"失踪案"

模型可能会漏掉你认为"必填"的字段,或者自作聪明地修改了键名(比如把 user_name 改成了 username)。

  • 后果 :程序访问时触发 KeyError

3. 类型"变色龙"

最典型的例子:你期待 tags 是一个数组 ["A", "B"],模型却返回了逗号分隔的字符串 "A, B"

  • 后果 :下游的 .map()foreach 逻辑直接崩溃。

03. 核心观念:AI 输出是"不可信输入"

在传统工程中,我们对用户提交的表单、第三方接口的返回都会进行严格的校验。AI 输出本质上也是一种"外部输入",而且是比第三方接口更不稳定、更不可控的输入。

优秀的 AI 工程师不相信"概率",只相信"防御"。


04. 实战:如何优雅地"接住"模型输出?

不要只写 json.loads。一个工业级的解析流程应该是这样的:

❌ 试玩版代码(极脆)

python 复制代码
response = get_ai_response(prompt)
data = json.loads(response)
print(data['tags'][0]) # 万一 tags 是字符串?万一 data 是空?

✅ 工程版代码(稳健)

python 复制代码
def safe_parse_tags(ai_output: str):
    try:
        data = json.loads(ai_output)
        
        # 1. 结构校验
        if not isinstance(data, dict):
            return []
            
        # 2. 字段与类型强校验
        tags = data.get('tags')
        if isinstance(tags, list):
            return tags
        elif isinstance(tags, str):
            # 这里的"防御"体现为:即便模型给错了类型,我们也尝试修复它
            return [t.strip() for t in tags.split(',')] 
            
        return [] # 兜底逻辑
    except (json.JSONDecodeError, Exception):
        return [] # 彻底失败时的安全降级(降级思维)

05. 进阶:引入 Schema 验证

在复杂的 AI 项目中,手动写 isinstance 太痛苦了。业界标准的做法是引入 Pydantic (Python)或者 Zod(TypeScript)。

python 复制代码
from pydantic import BaseModel, Field, validator
from typing import List

class ProductSchema(BaseModel):
    title: str
    price: float
    tags: List[str] = Field(default_factory=list)

    @validator('tags', pre=True)
    def handle_tags_string(cls, v):
        if isinstance(v, str):
            return [t.strip() for t in v.split(',')]
        return v

通过 Schema,你可以把"不确定"的模型输出,强行约束为"确定"的程序对象。这就是从"调包"到"工程"的跃迁。


06. 结语:工程感的起点

很多人问:会调 API 就算 AI 工程师了吗?

我的回答是:当你开始不再迷信模型输出,而是像对待任何"不可信输入"一样去解析、校验和兜底时,你才算真正开始了 AI 工程化的修行。

一句话总结:结构化输出解决的是"模型怎么说",而结构化消费解决的是"程序怎么活"。


讨论区:你在解析 AI 返回的 JSON 时遇到过哪些离谱的"幻觉"?你是怎么做兜底的?欢迎交流!


本文首发于掘金,记录前端开发者向 AI 工程转型的防御性编程实践。

相关推荐
Warren2Lynch2 小时前
AI 驱动的 UML 图表支持全景指南
人工智能·架构·uml
软件工程师文艺2 小时前
从0到1:Claude Code如何用React构建CLI应用
前端·react.js·前端框架
小鱼~~2 小时前
什么是父进程
人工智能
M ? A2 小时前
Vue 迁移 React 实战:VuReact 一键自动化转换方案
前端·vue.js·经验分享·react.js·开源·自动化·vureact
yuki_uix2 小时前
重排、重绘与合成——浏览器渲染性能的底层逻辑
前端·javascript·面试
找了一圈尾巴2 小时前
OpenClaw技能实战:Experience Distiller 让AI从错误中自我进化
人工智能·openclaw
蕤葳-2 小时前
AI项目经验在招聘中的作用
人工智能
devpotato2 小时前
人工智能(四)- Function Calling 核心原理与实战
java·人工智能
进击的野人2 小时前
MCP协议:让AI应用像插USB一样连接外部世界
人工智能·agent·mcp