JSON 转 JSON Schema

一键将 JSON 转换为 JSON Schema draft-07,自动推断类型、必填字段和嵌套结构。免费、在浏览器中处理,无需注册。

  • 在浏览器中处理
  • 数据不离开你的设备
  • 免费 · 无需注册
清空输入、生成的 Schema 和错误信息。在工具内按 Ctrl/⌘+L 也可清空,并返回输入 JSON。
修改示例 JSON 或输入自己的数据。每次输入变化立即生成 draft-07 JSON Schema。数组会合并全部元素;每个样本对象都具有且非 null 的键会列为必填。
JSON Schema (draft-07)
复制完整生成的 Schema。输出为只读;请粘贴到编辑器中调整约束或必填字段。输出为空时不复制。

输入 JSON 以生成 draft-07 Schema。

示例、说明与常见问题 带实际输出的示例、与同类工具的差别,以及常见问题。

JSON Schema 是什么

JSON Schema 用 JSON 描述 JSON 数据的结构:每个字段是什么类型、哪些字段必须有、嵌套对象长什么样。Ajv 这类校验器拿它检查数据,接口校验、代码生成和文档都会用到。这个工具从一份样本 JSON 反推出 draft-07 的 Schema,省去从零手写的工作。

理解输出结果

生成的 Schema 始终包含指向 draft-07 的 $schema 字段。 对象属性根据 JSON 的键名推断,required 数组列出所有非 null 键。 数组的 items 根据实际元素推断类型。

生成后的优化建议

生成的 Schema 只是起点,常见的优化包括:为字段添加 description 说明、 用 minLength 或 pattern 收紧字符串约束、 将可选字段从 required 中移除, 以及为枚举类字段添加 enum 限制。

示例

输入:

{
  "orderId": 1001,
  "total": 59.9,
  "coupon": null,
  "items": [{ "sku": "A1", "qty": 2 }],
  "tags": []
}

输出:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "orderId": { "type": "integer" },
    "total": { "type": "number" },
    "coupon": { "type": "null" },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "sku": { "type": "string" },
          "qty": { "type": "integer" }
        },
        "required": ["sku", "qty"]
      }
    },
    "tags": { "type": "array", "items": {} }
  },
  "required": ["orderId", "total", "items", "tags"]
}
  • 整数生成 integer,小数生成 number。如果 qty 可能是 1.5,改成 number。
  • 样本里 coupon 是 null,所以类型为 null,且不进 required。如果它也可能是字符串,把类型改成 ["string", "null"]。
  • 空数组生成 "items": {},任何元素都能通过。

示例:高德地图地理编码返回

高德地图 Web 服务 API 的地理编码接口返回 JSON。文档在返回结果说明的「提示」里写明:部分返回值存在时以字符串类型返回,不存在时以数组类型返回。下面按文档字段写了两条结果(坐标等值为示意),第二条没有街道和门牌:

{
  "status": "1",
  "count": "2",
  "info": "OK",
  "geocodes": [
    { "district": "朝阳区", "street": "阜通东大街", "number": "6号", "location": "116.483038,39.990633", "level": "门牌号" },
    { "district": "朝阳区", "street": [], "number": [], "location": "116.480881,39.989410", "level": "兴趣点" }
  ]
}

生成:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "status": { "type": "string" },
    "count": { "type": "string" },
    "info": { "type": "string" },
    "geocodes": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "district": { "type": "string" },
          "street": { "type": ["string", "array"], "items": {} },
          "number": { "type": ["string", "array"], "items": {} },
          "location": { "type": "string" },
          "level": { "type": "string" }
        },
        "required": ["district", "street", "number", "location", "level"]
      }
    }
  },
  "required": ["status", "count", "info", "geocodes"]
}
  • status 和 count 在样本里是字符串,所以类型是 string。写成数字 1 的数据会被拒绝。文档说 status 只有 0 和 1 两个值,需要限定时自己加 "enum": ["0", "1"]。
  • street、number 一条是字符串、一条是 [],合并后类型是 ["string", "array"],带 "items": {},两种写法都能通过。如果样本里只有带门牌的那一条,生成的 Schema 会要求 street 是字符串,遇到 [] 就校验失败。所以样本要同时包含有值和没值的记录。
  • 坐标 location 是 "经度,纬度" 一个字符串,工具不会拆开,也不会检查格式;需要时加 pattern。

用 Ajv 校验

Ajv 8 默认的 Ajv 类支持 draft-07。format 关键字需要 ajv-formats,不装的话 compile() 会抛出 unknown format "email":

import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv();
addFormats(ajv);

const validate = ajv.compile({
  type: 'object',
  properties: {
    email: { type: 'string', format: 'email' },
    coupon: { type: ['string', 'null'] },
  },
  required: ['email'],
  additionalProperties: false,
});

validate({ email: 'a@example.com', extra: 1 }); // false: must NOT have additional properties

生成器不会加 format、minimum、maxLength、pattern、enum 或 additionalProperties: false,按数据必须满足的规则自己补上。

限制

  • 数组元素会合并。 对 [{"id": 1, "name": "Alice"}, {"id": 2, "email": "b@example.com"}],items 列出 id、name、email,只有每个元素都有的 id 是必填。同一数组里的整数和小数合并为 "number"。生成的 schema 一定能通过它的样本;GenSON 也是这样合并样本的。
  • 必填项来自样本。 单个对象里所有非 null 的键都进 required。数据里可选、但样本里出现了的字段,需要自己从 required 删掉。
  • 混合类型生成类型列表。 [1, "x", {"a": 1}] 这样的数组生成 "type": ["integer", "string", "object"],旁边带对象的 properties 和 required,这两个关键字只作用于对象元素。
  • 只输出 draft-07。 要用 2020-12,改 $schema 并使用 Ajv 的 Ajv2020 类。

FAQ

此工具生成哪个版本的 JSON Schema?

此工具生成 JSON Schema draft-07,这是目前支持最广泛的版本之一,兼容 AJV、jsonschema(Python)等主流验证器,也可以直接用于 ZeroTool 的 JSON Schema 验证器。

如何确定必填字段?

输入 JSON 对象中所有非 null 的属性都会被加入 required 数组。null 值被排除,因为无法保证其必然存在。对象数组里,只有每个对象都有且不为 null 的键才是必填。您可以根据实际需求编辑输出的 Schema 来调整必填列表。

支持嵌套对象和数组吗?

支持。工具会递归处理嵌套对象和数组。数组的 items schema 由全部元素合并得出,每个元素都能通过,嵌套对象会生成对应的 properties 和 required 数组。

生成的 Schema 可以直接用于验证吗?

可以。将生成的 Schema 粘贴到 ZeroTool 的 JSON Schema 验证器或任何基于 AJV 的验证器中使用。您可能需要进一步完善可选字段,或添加 minLength、minimum、pattern 等额外约束。

JSON 会发送到服务器吗?

不会。Schema 在浏览器标签页里随输入生成,输入的 JSON 不会发送到服务器,也不会保存到浏览器存储。编辑完输入框、焦点移开时,或复制 Schema 时,页面的统计只记录一次使用事件(工具名和动作 convert 或 copy),不包含 JSON 或 Schema 内容。

接口没有值时返回 [] 而不是 null,生成的 Schema 会怎样?

工具只看样本:同一个键在一条记录里是字符串、在另一条里是 [],类型就写成 ["string", "array"],并带 "items": {},两种写法都能通过。高德地图 Web 服务 API 的地理编码文档就写明部分返回值不存在时以数组类型返回。如果样本里只出现过字符串,生成的 Schema 会拒绝 [],需要把两种记录都放进样本,或手动改类型。