YamlBox

JSON 工具 · 6 分钟阅读

JSON 到 JSON 模式:从样本有效负载到合约

JSON 到 JSON 模式转换采用了一个可以工作并生成其形状的机器可读描述的示例。该描述可以验证未来的有效负载、生成文档或驱动类型化代码 - 但前提是您将生成的模式视为初稿。推断看到一个样本,一个样本就是一个非常自信的骗子。

已更新

推论能看到什么和不能看到什么

一个好的转换器可以从单个文档中准确地导出类型、嵌套、数组项形状和属性名称。它无法得出的是意图。它不知道某个字段是可选的,因为该特定记录碰巧包含该字段,也不知道字符串是电子邮件地址,数字是正整数,或者值来自固定集。因此,导出的所有内容都被标记为 `required`,这是合同草案的正确默认值,并且未经审查就发货是错误的。

强化生成的模式

  1. 比较两个或三个真实样本:任何样本中缺失的键都应落在 `required` 范围内。
  2. 在已知含义的地方添加 `format` — `date-time`、`email`、`uri`、`uuid`、`ipv4`。
  3. 当该字段确实具有固定词汇(例如状态或区域)时,将开集转换为 `enum` 值。
  4. 用 `minimum`、`maximum` 和 `multipleOf` 收紧数字,这样负数就无法验证。
  5. 仅当必须拒绝未知密钥时才添加 `additionalProperties: false` — 否则保持模式开放以实现前向兼容性。

需要的是一个承诺,而不是一个观察。将某个字段标记为必填字段,因为您的一个样本包含该字段,这是推断模式破坏真实集成的最常见方式。

模式的立足点

实用价值体现在边界上:在信任 Webhook 有效负载之前对其进行验证,检查 CI 中的固定文件,以便测试因格式错误的数据而不是令人困惑的空错误而失败,为永远不会阅读服务器代码的人记录 API 响应,以及生成类型化客户端。 JSON 模式也是阻止配置更改悄悄改变公共响应的最便宜的方法,因为验证器在构建时而不是在生产中捕获它。

                {
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "required": ["id", "email"],
  "properties": {
    "id": { "type": "string", "format": "uuid" },
    "email": { "type": "string", "format": "email" },
    "plan": { "type": "string", "enum": ["free", "pro", "team"] }
  }
}
              

将其保留在版本控制中

生成的模式一旦没有人拥有它们,就会发生漂移。将强化文件提交到生成数据的代码旁边,从 CI 中的验证器引用它,并仅在合约真正更改时重新生成 - 将模式视为形状的真实来源,将样本视为证据,而不是相反。

浏览器中的推理

真实的有效负载充满了标识符、电子邮件和令牌,因此上传示例的 JSON 到 JSON 模式转换正在将生产数据移交给纯粹的机械操作。本地推断将有效负载保留在选项卡中,让您可以毫不犹豫地粘贴客户记录,并且可以在网络断开的情况下工作。

JSON 至 JSON 架构 — 常见问题

为什么每个字段都按要求输出?

因为推理会看到一个样本,并且该样本包含每个字段。必需意味着保证,因此生成的模式是一个起点:比较几个样本,然后删除有时不存在的键,并在您知道真正规则的地方添加 `format` 或 `enum` 约束。

我应该使用哪个 JSON 架构草案?

新工作的 2020-12 草案 — 这是当前规范,并得到 ajv 等验证者的良好支持。如果您要与固定到草案 07 的系统集成,请继续生成草案 07 文档;两者的主要区别在于您可能不需要的新关键字。

JSON 模式也可以验证数组吗?

是的。数组推断会生成描述元素形状的 `items` 模式,并且在现代草稿中可以使用 `prefixItems` 检查单个元素形状。合并两个具有不同元素形状的样本,您将看到哪里需要 `oneOf`。

这篇文章中提到的工具

浏览 19 工具的完整列表

更多文章可供阅读

6 分钟阅读

JSON diff:比较数据的实际结构

将两个 JSON 有效负载与结构性 JSON 差异进行比较,忽略按键顺序和空格,突出显示移动的值,并说明文本差异为何会产生误导。

所有19帖子→