Claude JSON 稳定输出:Schema 校验与修复回路(Kotlin)

1)先立规矩:你要的不是"像 JSON",而是"只输出 JSON"

最容易失败的提示词长这样:

请用 JSON 输出,并解释一下原因

这会让模型同时做两件事:结构化 + 自由文本。线上一定会有人撞坑。

建议你把底线写死(短、硬、可检查):

  • 只允许输出一个 JSON 对象(或数组)
  • 不允许 Markdown 代码块
  • 不允许额外文本
  • 信息不足时输出 { "error": "...", "need": [...] }

2)提示词模板:schema + 规则 + 唯一出口

2.1 最小模板(低风险任务)

text 复制代码
你必须只输出一个 JSON 对象,不要输出任何额外文本,也不要使用 Markdown。
信息不足的字段写 null。

schema:
{
  "intent": "string",
  "priority": "low|medium|high",
  "summary": "string",
  "tags": ["string"]
}

2.2 更稳模板(推荐):加规则 + 唯一出口

text 复制代码
你必须只输出 JSON(不要 Markdown,不要解释)。
必须满足:
1) 必须包含字段:intent, priority, summary, tags
2) priority 只能是 low/medium/high
3) tags 必须是数组,最多 5 个
4) summary <= 60 字

如果无法满足规则,请只输出:
{ "error": "原因", "need": ["缺少的信息"] }

你会发现:"唯一出口"非常重要。它能把模型想说的废话收敛到结构里。


3)修复回路:解析失败别硬扛,给自己一个稳定的 fallback

生产里我一般按三层兜底:

  1. 直接解析(成功就返回)
  2. 轻量净化 (截取第一个 { 到最后一个 }
  3. 二次修复(把失败样本喂回模型,让它只输出最终 JSON)

如果你没有第 3 步,线上总会出现"某些输入必炸"的角落案例。


4)Kotlin 实战:kotlinx.serialization + 规则校验 + 净化截取

4.1 Gradle 依赖

kotlin 复制代码
dependencies {
  implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
}

4.2 数据模型(包含 error/need 兜底字段)

kotlin 复制代码
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

@Serializable
data class Ticket(
  val intent: String? = null,
  val priority: Priority? = null,
  val summary: String? = null,
  val tags: List<String> = emptyList(),
  val error: String? = null,
  val need: List<String> = emptyList()
)

@Serializable
enum class Priority {
  @SerialName("low") LOW,
  @SerialName("medium") MEDIUM,
  @SerialName("high") HIGH
}

private val json = Json {
  ignoreUnknownKeys = true
  isLenient = true
  explicitNulls = false
}

4.3 净化:截取 JSON 主体

kotlin 复制代码
fun sanitizeToJsonObject(raw: String): String {
  val start = raw.indexOf('{')
  val end = raw.lastIndexOf('}')
  if (start < 0 || end <= start) return raw.trim()
  return raw.substring(start, end + 1).trim()
}

4.4 解析 + 规则校验

kotlin 复制代码
data class Validation(val ok: Boolean, val message: String)

fun validate(t: Ticket): Validation {
  if (t.error != null) return Validation(true, "error-mode")
  if (t.intent.isNullOrBlank()) return Validation(false, "intent missing")
  if (t.priority == null) return Validation(false, "priority missing")
  if (t.summary.isNullOrBlank()) return Validation(false, "summary missing")
  if (t.tags.size > 5) return Validation(false, "too many tags")
  if (t.summary.length > 60) return Validation(false, "summary too long")
  return Validation(true, "ok")
}

fun parseTicket(raw: String): Ticket? =
  runCatching { json.decodeFromString(Ticket.serializer(), raw.trim()) }.getOrNull()

fun parseWithFallback(raw: String): Ticket? {
  parseTicket(raw)?.let { return it }
  val sanitized = sanitizeToJsonObject(raw)
  return parseTicket(sanitized)
}

你现在已经能处理 80% 的"夹文本/代码块"问题。剩下那 20%,需要二次修复回路。


5)二次修复回路(推荐):把失败样本再喂回 Claude

思路很简单:当 parseWithFallback() 仍失败时,触发一次修复调用:

修复提示词(示例):

text 复制代码
下面是一段"可能包含多余文字"的输出。请你只输出一个合法 JSON,并且必须符合 schema:
{ ... }
禁止 Markdown,禁止解释。

原始输出:
<<<
{原文粘贴}
>>>

这一轮通常用 Sonnet 就够了,不要用 Opus 硬抬成本。


6)把 schema/校验/修复策略集中管理(147api)

结构化输出最怕的是:每个服务都写一套 schema,每次改字段都要全量发版。

更合理的做法是把这些能力集中到统一接入层:

  • schema 版本化(v1/v2)
  • 校验与修复回路统一实现
  • 按项目/用户做限流与配额,避免修复回路把 429 撞爆

如果你不想自建网关,可以了解下 147api:按其介绍,它提供 OpenAI 风格的聚合管理与 key 管理能力。把接入层工程收口后,业务侧就只需要调用一个稳定接口。


一页清单

  • 提示词:只输出 JSON,禁止 Markdown/解释
  • schema:字段/类型/枚举写清楚
  • 规则:写成可检查项(长度、必填、数组上限)
  • 唯一出口:{error, need} 兜底
  • 解析:反序列化失败要有 fallback(净化/修复回路)
  • 观测:记录失败样本,反推 schema 与规则
相关推荐
pengyu15 分钟前
【Kotlin 协程修仙录 · 化神境 · 后阶】 | 异常天劫:Flow 异常处理的终极奥义与重试之道
android·kotlin
空堂与归29 分钟前
单机 Python 跑不动?Ray 分布式计算框架让 AI 训练提速 10 倍
开发语言·人工智能·python
pengyu33 分钟前
【Kotlin 协程修仙录 · 化神境 · 中阶】 | 多播奥义:SharedFlow 高级配置与 Channel 的抉择之道
android·kotlin
JacksonMx36 分钟前
Java 线程池:复用、Spring 管理、监控与线上故障排查全指南
开发语言·python
脉动数据行情43 分钟前
Python WebSocket 实现融通金实时行情监听
开发语言·python·websocket
only-qi44 分钟前
Python Agent 开发速通清单
开发语言·python
zq_63891 小时前
ObjectModel_diagram.pdf 文档详细总结
开发语言·matlab
AC赳赳老秦1 小时前
个保法下数据处理:OpenClaw 自动过滤公开数据中的个人信息,保障采集分析合规性
java·python·sqlite·json·php·deepseek·openclaw
Web - Anonymous1 小时前
Vue3 + Element Plus 集成 JSON Editor 实现实时校验 JSON 编辑器(高亮/暗亮主题/分栏回显/组件复用) - 附完整示例
vue.js·编辑器·json
自己的九又四分之三站台2 小时前
C# 接入 RasterLite2:从原生 DLL 加载到 Coverage、Section、Tile 验证
开发语言·c#·地理信息