SchemaSafe博客
无需LLM的JSON模式验证
模式验证属于确定性工具的范畴:相同的输入每次都会产生相同的通过或失败结果。LLM可以解释为什么一个文档失败或根据示例草拟一个模式,但通过或失败的结果应该来自真正的验证器。当解释和决策之间的界限保持清晰时,合同仍然是可以测试和信任的东西。
决定论是产品
当我设计一个验证器时,我专注于实例树的遍历。每一步都会产生一个错误对象,携带一个 JSON 指针路径、失败的关键字和一个简短的消息。因为遍历按照相同的算法执行相同的数据,错误列表在每次运行中都是相同的。这种可重复性使得团队可以将验证视为一个永远不会在没有真正的模式或输入更改的情况下改变其判决的门槛。
JSON 指针路径直接映射到表单字段或 API 响应键。前端可以使用指针 /items/2/name 高亮显示第三个项目的名称字段,而无需任何额外的翻译层。这种映射是决定论的,所以相同的指针总是指向相同文档形状中的相同位置。
在 CI 中,我将验证器运行在测试套件和任何生成的固定数据上。如果验证器返回一个空错误数组,则构建继续;任何非空数组都会使构建失败,并且错误有效载荷作为工件发布。因为输出是机器可读的,下游步骤可以计算错误、按指针对其进行分组,或在拉取请求上发布一条评论,显示确切的失败路径。
LLM 获得其地位的地方
我只将语言模型用于不需要真假判决的任务。该模型永远不会决定通过或失败;它只会生成建议,人类或工具可以审查。
给定一批示例 JSON 文档,我会提示模型生成一个捕获观察到的类型、必需字段和基本模式的 Draft 2020-12 模式。我将输出作为起点;我将其运行通过验证器,以查看它是否接受示例,然后我手动调整或放松约束。
当验证器返回错误数组时,我会将每个错误对象提供给模型,并请求它用简单语言重写消息。该模型可以将“failed keyword “required” at pointer /user/profile/age”转换为“用户配置文件缺少年龄字段,您的服务期望它是一个整数。”这有助于不熟悉 JSON 模式关键字的 API 消费者。
通过向模型展示一份常见验证错误列表,我可以要求它提出额外的约束,例如最小字符串长度或标识符模式。我审查每个建议,添加有意义的建议,然后再次运行验证器以确认新的模式仍然通过已知的良好示例。
为了安全,我将模型放在内部 API 后面,并记录每个提示和响应。日志允许我审计模型是否曾经尝试影响决策边界,这是因为我从不将其输出传递给验证器作为规则。
在CI和边缘运行验证
相同的模式应该保护代码仓库和实时服务。我在两个地方运行验证器:
仅在网关处运行验证会使内部服务暴露于漂移;如果网关模式被更新,但下游服务忘记拉取更改,错误的数据可能会通过。通过将验证器嵌入到服务中,我可以保证合同在代码存在的任何地方被执行。
当验证失败时,我返回HTTP 400,带有一个包含错误对象数组的JSON正文。每个错误对象包括:
客户端可以解析这个数组并显示内联表单错误,这比通用的“验证失败”字符串加快了集成工作的速度。
因为验证器是无状态和确定性的,我可以在两个地方使用相同的二进制文件或库,而不必担心可能导致分歧的隐藏状态。
草稿生成与治理
SchemaSafe 清晰地分离了关注点:
这种分离保持了合同的可审计性。我可以指向存储库中的特定模式文件,注意验证器版本,并显示相同的输入始终产生相同的结果。模型的贡献存在于单独的日志或拉取请求附加的注释中;它永远不会成为不可变的决策记录的一部分。
当我需要更新模式时,我遵循以下步骤:
在整个流程中,验证器是守门人;模型永远不会有最终的决定权。
这不是什么
这种方法不能保证每个无效文档在到达用户之前都会被捕获。如果开发人员故意绕过中间件,或者验证器中的漏洞让错误通过,仍然可能出现坏数据。我不声称100%的覆盖率;我只声称检查是确定性的和可重复的。
它不是精心设计的API的替代品。模式可以描述形状和基本约束,但不能表达依赖于外部状态或复杂跨字段逻辑的业务规则。这些规则仍然需要单元测试或运行时保护。
它不能保证LLM总是产生有用的解释。模型可能会偶尔错过细微差别或产生误导性的重写。我将其输出视为人类可以接受、编辑或丢弃的建议。
最后,它不是安全的银弹。虽然输入验证可以减少许多注入风险,但我仍然遵循OWASP关于提示注入(https://genai.owasp.org/llmrisk/llm01-prompt-injection)和CI/CD中的凭证卫生(https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-06-Insufficient-Credential-Hygiene)的指导,以保持周围管道的安全。
参考资料
https://genai.owasp.org/llmrisk/llm01-prompt-injection
https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-06-Insufficient-Credential-Hygiene
https://ajv.js.org/json-schema.html
https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html
常见问题
验证必须是可复现的:相同的输入,相同的结果。模型的判断可能会在不同运行之间变化,这对于一个控制部署的合同来说是不可接受的。验证器决定;模型解释。
从示例中草拟一个模式,重写验证错误以供人类阅读,或者建议为什么某个字段被省略。这些都是在真正的验证器之上提供的辅助功能,而不是替代品。
不。验证您控制的服务中的传入请求,以便错误消息包含域上下文。在CI中使用相同的模式运行固定值,并将模式更改视为潜在的破坏性更改。
2020-12草案是现代验证器(如Ajv v8)支持的稳定版本,并与OpenAPI 3.1保持一致。在每个文件中固定$schema URL,以免行为发生漂移。
尝试产品:SchemaSafe
2026-09-16 · 仅主源 · 无虚假流量指标
相关文章
常见的 JSON 模式编写错误
探索完整的 AI 微 SaaS 主题矩阵 →
为什么不让大语言模型决定JSON是否有效?
验证必须是可复现的:相同的输入,相同的结果。模型的判断可能会在不同运行之间变化,这对于一个决定部署的合同来说是不可接受的。验证器决定;模型解释。
大语言模型在模式中真正有用的地方在哪里?
从示例中草拟一个模式,重写验证错误以供人类阅读,或者建议为什么省略了某个字段。这些都是在真正的验证器之上的辅助功能,而不是替代品。
验证应该只在网关运行吗?
不。验证传入的请求在您控制的服务中,以便错误消息包含域上下文。在CI中使用相同的模式运行固定值,并将模式更改视为潜在的破坏性更改。
当前要固定的JSON模式草案是什么?
2020-12草案是现代验证器(如Ajv v8)支持的稳定版本,并与OpenAPI 3.1保持一致。在每个文件中固定 $schema URL,以便行为不会发生变化。
仅供决策支持,不代替正式的模式审查或认证审计。