ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

大模型返回了 JSON,为什么 Java 还是解析失败

大模型返回了 JSON,为什么 Java 还是解析失败

本文基于「码上面试平台」当前代码整理,讨论的是模型响应到业务字段之间的解析边界。

“让模型只返回 JSON”为什么还不够?

提示词里写了“只返回 JSON”,模型却可能用 Markdown 代码围栏包起来,也可能先说一句解释;模型服务还可能把内容放在choices[0].message.content或流式响应的choices[0].delta.content里。再往下,工作流本身也可能把真正的业务对象嵌在json字段中。

因此,解析大模型输出不是一次JSON.parseObject()就结束。代码需要先识别响应包络,再找到业务对象,最后检查必需字段是否满足当前流程。

先把传输响应和业务对象分开

项目的InterviewResponseParser先尝试从常见模型响应形状提取 content:

choices[0].delta.content choices[0].message.content content 原始响应文本

随后才尝试把 content 当作 JSON 对象解析。如果原始响应不是模型包络,也会尝试直接解析。对于顶层json字段,解析器还会继续尝试把它展开成真正的业务字段。

这个分层让我觉得很重要:传输 SDK 升级导致外层响应形状变化,和评分工作流把score改名,是两种不同的契约变更。前者属于响应解包,后者属于业务字段契约,不应该混在一个大try/catch里处理。

当前解析器具体做了哪些容错?

去代码围栏,必要时提取 JSON 子串

解析器会去掉 Markdown 的 ```json 围栏;如果整段文本不是合法 JSON,会尝试取第一个{到最后一个}之间的内容再解析。它适合处理模型在对象前后多写少量说明的情况,但不是通用的 JSON 修复器。对象内本身有语法错误,或者前后夹着多个互不相关的对象时,这个策略仍然可能失败。

递归寻找目标字段

提取题目时,调用方给解析器传入questions、sugest、suggestions、resumeScore、type等目标字段。解析器会在嵌套的 Map/List 结构中查找第一个包含目标字段的对象。InterviewJsonValueNormalizer则把 Fastjson 的JSONObject、JSONArray转成普通 Java Map/List,方便下游统一处理。

兼容常见的类型差异

分数可以是 Number,也可以是数字字符串;解析后四舍五入并限制在 0 到 100。布尔值兼容true、1和yes;列表字段兼容 JSON 数组、字符串列表和逗号/分号分隔文本。

这些兼容手段可以减少模型输出的小波动,但它们不能代替业务校验。比如解析器能读到一个对象,不代表题目列表非空;能读到评分字段,也不代表答案评估链路的全部必要字段都齐全。

解析成功和业务成功是两回事

出题链路拿到结构化 Map 后还会验证questions是否为空,再缓存题目和初始化 flow。答题评分链路会继续检查score能否解析;评分缺失时会返回失败,而不是把一个空 Map 当成有效评价。

这也是我不想把所有容错都塞进 Parser 的原因:Parser 负责把不同响应形状归一化成可读对象,调用方负责根据业务场景判断哪些字段必需、哪些字段可以为空。否则解析层会悄悄替业务做决定,问题发生时也很难定位。

我会记录的几个坑

  1. 只测“合法 JSON”不够。至少要覆盖代码围栏、包络响应、嵌套json、数字字符串和错误字段类型。
  2. 字段别名是协议债务。sugest这样的历史拼写需要兼容,但应记录来源和退出条件。
  3. 容错不能吞掉关键字段错误。questions或score缺失应该由业务层明确失败,并保留诊断信息。
  4. 原始响应便于排查,但要控制敏感信息。简历内容、模型凭证和用户隐私不能因为调试方便就进入公开日志或博客截图。
  5. 递归找对象不等于 Schema 校验。生产链路还要定义字段类型、范围、必填项和错误分类。

我的复盘:在边界做兼容,在业务层做判断

当前实现选择在解析边界容忍若干常见形状,再由提题或评分服务判断业务字段是否够用。这个分工比“模型必须永远严格按格式输出”更现实。

但容错越多,越要防止错误输出被误认为成功。对关键 AI 工作流,我会倾向于维护一个明确的字段契约和一组脱敏样例,用它们验证解析器及业务校验;兼容历史格式可以保留,但不能只靠线上用户帮忙发现回归。

源码入口

  • 模型响应包络、结构化结果和字段转换:admin/src/main/java/com/hewei/hzyjy/xunzhi/interview/shared/InterviewResponseParser.java
  • Fastjson 结构归一化:admin/src/main/java/com/hewei/hzyjy/xunzhi/interview/shared/InterviewJsonValueNormalizer.java
  • 提题业务字段校验:admin/src/main/java/com/hewei/hzyjy/xunzhi/interview/flow/extraction/InterviewQuestionExtractionService.java
  • 评分业务字段校验:admin/src/main/java/com/hewei/hzyjy/xunzhi/interview/flow/answer/InterviewAnswerPipeline.java

发布标签

JavaJSON大模型应用数据解析Spring Boot踩坑记录

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进