📖
blog
  • README
  • JavaScript
    • 元素的宽高位置信息梳理
    • dom-align 源码浅析
    • Event Loop
    • 函数实参为对象时的陷阱
    • export 与 utils 方法书写规范
    • 手写 Promise 及相关代码理解
    • call,apply,bind 等函数的模拟实现
    • JavaScript继承
    • JavaScript 数据类型与类型判断
    • for..of 和 for..in 的区别
    • 写给自己看的 next 函数
    • JS 可选链与双问号
    • mouseenter 与 mouseover 事件的区别
    • Immutable相关知识
  • CSS
    • 不简单的 z-index
    • 两列布局,三列布局
    • CSS 居中方案整理
    • CSS 像素,设备像素,2倍图梳理
    • iconfont 的使用
  • Node JS
    • 实现简易的 express
  • React 核心知识点整理
    • 高阶组件
    • React 事件处理
    • React Hooks
    • React Context
  • React 状态管理
    • Redux 基础概念
    • Redux 中间件和异步操作
    • Redux Saga
    • Redux 只能有一个 store 对象嘛
  • React 开发实践
    • Ant Design Menu 组件的使用与深入
    • 讲讲吸顶效果与 react sticky
    • 基于 express,搭建 react 的开发环境
    • 通过 antd input 组件分析受控与非受控组件
    • DebounceClick 组件
    • react component Align 组件分析
    • React Portal 之事件冒泡
    • React Transition Group 源码浅析
    • React.cloneElement 父组件向子组件注入 props
    • 一次 Align 组件的问题记录
    • 如何知道子组件的类型
    • React Router 源码简单分析
    • React Redux 源码简单分析
  • Vue.js
    • Vue.js 概览
    • scoped 样式中的 deep
  • TypeScript 语法
    • 基础类型
    • 变量声明
    • 接口
    • 类
    • 函数
    • 泛型
    • 枚举
    • 类型推论
    • 类型兼容性
    • 高级类型
    • Symbol
    • 迭代器和生成器
    • 模块
    • 命名空间
    • JSX
  • 玩转 webpack
    • 第一章: webpack 与构建发展简史
    • 第二章:webpack基础用法
    • 第三章:webpack进阶用法
    • 第四章:编写可维护的 webpack 构建配置
    • 第五章:webpack构建速度和体积优化策略
    • 第六章:通过源代码掌握webpack打包原理
    • 第七章:编写Loader和插件
  • webpack 实践
    • 如何配置 output.library
  • 测试
    • 初识代码测试
    • Jest 中 如何测试 setTimeout
    • Jest Enzyme React 测试实践记录
  • WEB 开发,过往工作沉淀
    • Web安全(DVWA)
    • 内存泄露与事件移除的必要性
    • url to pdf api 与 服务部署踩坑记录
    • 前端调试指南
    • Markdown 转 email
    • github travis ci 自动部署
    • 浏览器缓存知识梳理
    • WEB 系统登录相关知识梳理
    • 将-Axios-请求参数和返回值进行格式化
    • source-map与源码调试
    • HTTPS
    • 使用 rollup 打造自己的 npm 包 (全流程)
    • father-build 是如何工作的
  • 书籍
    • 图解 HTTP 协议
    • 编写可维护的 JavaScript
    • 鸟哥的 Linux 私房菜
    • JavaScript Promise迷你书
  • Linux
    • vimtutor
    • CURL 使用指南
  • Nginx
    • 一次 nginx 分享
  • Git
    • Git Commit Message 须知
    • .gitignore 模板
    • git tag标签
  • 摄影
    • 摄影基础知识
    • 手机摄影从小白到大师
  • 翻译
    • log4js
    • log4js-node
    • 介绍GitLab上的CI/CD
    • 为GitLab Pages创建并调整GitLab CI/CD
    • 关于 rel=noopener
    • AngularJS 团队 Git 提交信息约定
    • JSON Schema
  • Lifehack
    • 20 个 Google 搜索 Tips 来高效使用 Google
    • 37 个高级 Google 搜索 Tips
Powered by GitBook
On this page
  • 一步步开始
  • 1. 介绍
  • 2. 开始 Schema
  • 3. 定义属性
  • 4. 深入属性
  • 5. 数据结构嵌套
  • 6. 引用外部的 Schema
  • 7. 看一下我们定义的 JSON Schema 最终对应的数据格式

Was this helpful?

  1. 翻译

JSON Schema

PreviousAngularJS 团队 Git 提交信息约定Next20 个 Google 搜索 Tips 来高效使用 Google

Last updated 4 years ago

Was this helpful?

一步步开始

1. 介绍

以下的例子,绝不能代表所有 JSON Schema 所能提供的价值。因此,你可能需要深入了解规范本身,在 查看更多。

让我们假设我们正在和一个 JSON 格式的产品目录打交道,这个目录有一个产品,这个产品有以下的属性:

  • 唯一标识符: productId

  • 产品名称: productName

  • 消费零售价: price

  • 一系列可选的标签: tags

例如:

{
    "productId": 1,
    "productName": "A green door",
    "price": 12.50,
    "tags": ["home", "green"]
}

通常来说,上面的例子有一些问题,以下列举一些:

  • 什么是 productId

  • productName 是否是必须的

  • price 能否为 0

  • tags 是否都是字符串

当你在讨论数据格式的时候,你需要 metadata 元信息 来表示这些 keys 属性 的含义,包括这些属性的有效值. JSON Schema 是一项被建议的 IETF 标准,用于回答这些数据的问题。

2. 开始 Schema

为了开始类型定义,我们先从一个简单的 JSON schema 开始.

我们从四个关键字属性开始,这些属性也用作 JSON 的属性.

是的,这项标准使用 JSON 数据文档,来描述数据文档,这些数据文档通常也是 JSON 数据,但是也可以是其他任意的内容类型,比如 text/xml

  • $schema 关键字声明,这个 schema 是根据标准的一个特定的草稿书写的,主要用于很多原因和版本控制(???,翻译不出来)

  • $id 关键字定义了这个 schema 的 URI,以及这个 schema 中引用的其它 URI 的 base URI

  • title 和 description 只是描述性的词. 他们不会给要检验的数据添加约束. 这两个关键词用于描述这项 schema 的目的

  • type 校验关键字定义了这项 JSON 数据的第一个约束,在这个例子中,它表明这个 JSON 数据是一个 JSON 对象

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/product.schema.json",
  "title": "Product",
  "description": "A product in the catalog",
  "type": "object"   // 对象
}

当我们开始 schema 之前,我们先介绍以下的术语:

3. 定义属性

productId 是一个数字,是一个产品的唯一标识。因为它是产品通用的标识,如果一个产品没有这一项,那么将是无意义的,因此,这个属性是required.

在 JSON Schema 中,我们添加:

  • properties 校验关键字

  • productId 属性

    • description 注释和 type 校验关键字尤其要注意,我们在前一章节中已经说过了它们的含义。

  • required 校验关键字列表有 productId

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  "properties": {                // 定义属性
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"          // 表明 productId 是个整数
    }
  },
  "required": [ "productId" ]   // 必填的属性
}
  • productName 是一个字符串值,用于描述产品。由于每个产品都有产品名称,所以这也是rquired。

  • 因为 required 校验关键字是一个字符串数组,我们可以添加多个属性。我们现在添加 productName

  • 实际上 productId 和 productName 并没有什么区别,我们为了完整性所以包含这两项,因为计算机关注的是标识符 productId,而人们更加关注名称 productName。

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"         // 表明 productName 是个字符串
    }
  },
  // 同时 productName 也是必填的
  "required": [ "productId", "productName" ]
}

4. 深入属性

对于商家而言,没有免费的产品

  • price 属性被添加近来,拥有通用的 description 注释和 type 检验关键字,这两个在之前都被提到过了。并且,也被添加到了 required 数组里了

  • 通过 exclusiveMinimum 校验关键字,我们指定 price 的值必须是大于 0 的值

    • 如果我们想要 price 大于等于 0, 那么我们可以使用 minimum 关键字

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
      "description": "The price of the product",
      "type": "number",    // 表明 price 属性是个数字
      "exclusiveMinimum": 0         // 而且大于0 (不能等于)
    }
  },
  // price 也是必填项
  "required": [ "productId", "productName", "price" ]
}

接下来,我们来到了 tags 属性

商家说了:

  • 如果有 tags,那么至少要有一个 tag

  • 所有的 tag 必须的唯一的,同属于一个产品的 tag 不能重复

  • 所有的 tag 都必须的文本类型

  • tags 非常好,但是不一定是 必填项

因此:

  • 添加 tags 属性,它拥有通用的注释和关键词

  • 这一次,type 校验关键字是 array

  • 我们介绍下 items 这个校验关键字,这样我们定义数组中的元素类型。在这个例子中,数组元素的 type 是 string

  • minItems 校验关键字用来确保数组中至少有一个元素

  • uniqueItem 校验关键字表明数组中所有的元素都是唯一的

  • 因为 tags 是可选的,因此我们不把它加到 required 中

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "tags": {
      "description": "Tags for the product",
      "type": "array",          // tags 是一个数组
      "items": {
        "type": "string"        // 数组元素是字符串
      },
      "minItems": 1,            // 至少有一个元素
      "uniqueItems": true       // 每一个元素都是唯一的
    }
  },
  "required": [ "productId", "productName", "price" ]
}

5. 数据结构嵌套

到目前为止,我们都在处理一个比较扁平的 JSON 结构,只有一层。这一节示范一下嵌套的数据结构。

  • 新增 dimensions 这个属性,因为它的 type 校验关键字是 Object, 我们可以使用 properties 校验关键字来定义一个嵌套的数据结构

    • 我们省略了 description 注释关键字来简化这个例子。当然通常建议不省略注释关键字。然而在这个例子中,这些属性名和数据结构大部分开发者都很熟悉。

  • 你会注意到 required 检验关键字的作用于适用于 dimensions 属性里,而不是在外面

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "tags": {
      "description": "Tags for the product",
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "dimensions": {           // 外层对象还拥有 dimensions 这个属性
      "type": "object",       // 这个属性的值是一个对象              
      "properties": {
        "length": {
          "type": "number"
        },
        "width": {
          "type": "number"
        },
        "height": {
          "type": "number"
        }
      },
      // dimensions 这个对象的,length, width, height 属性都是必须的
      "required": [ "length", "width", "height" ]
    }
  },
  "required": [ "productId", "productName", "price" ]
}

6. 引用外部的 Schema

到目前为止我们的 JSON Schema 都是自包含的. 在很多的数据结构中共享 JSON Schema 从而实现中可复用,可阅读和可维护是很常见的。

在这个例子中,我们介绍一个新的 JSON Schema,里面包含两个属性:

  • 使用 minmimum 校验关键字

  • 使用 maximum 校验关键字

  • 组合这两个,产生一个 range (范围的校验)

{
  // 前面提到了,id 可以作为引用的 URI
  "$id": "https://example.com/geographical-location.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Longitude and Latitude",
  "description": "A geographical coordinate on a planet (most commonly Earth).",
  "required": [ "latitude", "longitude" ],
  "type": "object",
  "properties": {
    "latitude": {           // 维度在 -90 到 90 之间
      "type": "number",
      "minimum": -90,
      "maximum": 90
    },
    "longitude": {
      "type": "number",     // 经度在 -180 到 180 之间
      "minimum": -180,
      "maximum": 180
    }
  }
}

// 即描述了一个对象,包含经度维度两个属性

接下来,我们引用这个 Schema , 这样就能组合成新的 Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from Acme's catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "tags": {
      "description": "Tags for the product",
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "dimensions": {
      "type": "object",
      "properties": {
        "length": {
          "type": "number"
        },
        "width": {
          "type": "number"
        },
        "height": {
          "type": "number"
        }
      },
      "required": [ "length", "width", "height" ]
    },
    "warehouseLocation": {
      // 我们新增这个属性
      "description": "Coordinates of the warehouse where the product is located.",
      // 引用上面定义的 Schema
      "$ref": "https://example.com/geographical-location.schema.json"
    }
  },
  "required": [ "productId", "productName", "price" ]
}

7. 看一下我们定义的 JSON Schema 最终对应的数据格式

{
    "productId": 1,
    "productName": "An ice sculpture",
    "price": 12.50,
    "tags": [ "cold", "ice" ],
    "dimensions": {      // dimensions 属性
      "length": 7.0,
      "width": 12.0,
      "height": 9.5
    },
    "warehouseLocation": {  // warehouseLocation 拥有 latitude 和 longitude 两个属性
      "latitude": -78.75,
      "longitude": 20.4
    }
}

: $schema 和 $id

: title 和 description

: type

英文原版
https://json-schema.org/specification.html
Schema Keyword (Schema 关键字)
Schema Annotations (Schema 注释)
Validation Keyword(校验关键字)