JSON Schema入门和应用

avatar
前端开发工程师 @bigo

file

本文首发于:github.com/bigo-fronte… 欢迎关注、转载。

JSON Schema入门和应用

何为JSON Schema?

JSON数据格式对于web开发者都为所熟悉,在平时的开发中离不开它,例如前后端数据传输格式,webpack配置文件,对象序列化等实际应用场景,通常都以JSON格式定义和储存。它以简洁易懂的结构、体积小的优点得以在各类编程语言中广泛流行。

那么什么是JSON Schema?
JSON Schema其实是对json数据格式的描述和规范,是对JSON格式一种约束,更明确地定义数据的类型和结构。伴随着JSON被创造出来,JSON Schema的诞生是必然的,类似其他数据格式YAML,也会创造YAML Schema的标准来进行规范,并使用这个规范来校验格式。这就好比有了Javascript,自然就会有Typescript,开发者更倾向于使用工具替代人为来进行约束,校验,使开发效率和开发质量大大加强。

掌握使用

举个简单的例子,你便清楚JSON Schema的使用

这里有两个对象a,b,唯一的区别是对象里的属性类型不同,当你想指定对象属性的类型时,假若你只想要字符串类型,那么可以使用JSON Schema来进行定义

{
  "type": "object",
  "properties": {
    "title": {
      "type": "string"
    }
  }
}
// right
var a = {
  title: '123'
}

// error
var b = {
  title: 123
}

上面是最简洁的JSON Schema对象定义,从中我们可以得知定义的变量类型是对象,而这个变量对象里具有title属性,title属性的类型是string类型。好了,到这里你已经掌握了JSON Schema使用,是不是好简单🐕。

当然,JSON Schema既然是一套标准和规范,那么就会有好多语义需要理解,下面说说常见用法

数据类型

在JSON Schema中使用最多的是type关键字,它包含了JSON格式的基本类型

类型描述
string字符串型,双引号包裹的 Unicode 字符和反斜杠转义字符
number数字型,包括整型(int)和浮点数型(float)
boolean布尔型,true 或 false
object对象型,无序的键:值对集合
array数组型,有序的值序列
null空型

关键字

以Object类型为例,列举在JSON Schma所经常用到的关键字

示例:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$id": "https://example.com/schemas/person",
  "title": "base info",
  "description": "base information about person",
  "type": "object",
  "required": ["name", "age", "phone"],
  "definitions": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 10
    }
  },
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 10
    },
    "age": {
      "type": "number",
      "minimum": 18,
      "exclusiveMinimum": true,
      "maximum": 65,
      "exclusiveMaximum": true
    },
    "phone": {
      "type": "string",
      "pattern": "^1\\d{10}$"
    },
    "parents": {
      "type": "array",
      "items": [{ "$ref": "#/definitions/name" }],
      "minItems": 1,
      "maxItems": 2,
      "uniqueItems": true
    },
    "address": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "enum": ["guangzhou", "beijing"]
        }
      }
    }
  }
}
关键字描述
$schema声明此json片段属于JSON Schema,并遵循所声明的JSON Schema版本规范
$id为JSON Schema声明一个统一资源标识符,使解析$ref时能够引用片段
title为JSON Schema文件提供标题
description为JSON Schema文件提供描述信息
definitions声明子schema,使解析$ref能够引用片段
$ref引用JSON Schema片段
required定义对象类型properties所声明的字段是否必须,值必须是数组,数组中的元素必须是字符串类型且唯一
type定义元素的类型
properties定义对象类型里的属性(键值对),每个字段的值都是一个有效的schema片段,用来限制每个字段的格式
minimum约束取值范围,标识取值范围应该大于或等于minimum
exclusiveMinimum假若minimum或exclusiveMinimum同时存在,且exclusiveMinimum为true,则取值范围大于minimum
maximum约束取值范围,标识取值范围应该小于或等于maximum
exclusiveMaximum假若maximum或exclusiveMaximum同时存在,且exclusiveMaximum为true,则取值范围小于maximum
minLength字符串类型数据的最小长度
maxLength字符串类型数据的最大长度
pattern使用正则表达式约束字符串类型数据
items用来定义数组类型的子元素,值必须为数组,且是一个有效的schema片段
minItems定义数组类型大小的最小长度
maxItems定义数组类型大小的最大长度
uniqueItems定义数组类型子元素是否必须唯一
enum用来限制值的范围,值必须在enum所指定的集合里面

以上是比较常用到的关键字,还有一些其他的关键字可以阅读官方文档进行深入地了解和使用

Understanding JSON Schema

进阶使用:

正则属性

提供patternProperties关键字,对属性字段名提供正则校验

{
  "type": "object",
  "patternProperties": {
    "^S_": { "type": "string" },
    "^I_": { "type": "integer" }
  }
}
// right
"{ "S_25": "This is a string" }"

// right
{ "I_0": 42 }
// error S_开头的字段名的值必须为字符串类型
{ "S_0": 42 }

// error I_开头的字段名的值必须为数值类型
{ "I_42": "This is a string" }

组合sechma

JSON Sechma提供一些关键字来讲多个子schema片段组合在一起,类似布尔算符AND, OR, XOR, 和 NOT,通过布尔逻辑来验证

关键字描述
allOf相当于AND布尔算符,必须满足所有的子schema校验
anyOf相当于OR布尔算符,必须满足任意子schema校验
oneOf相当于XOR布尔算符,必须满足其中一个子schema校验
not相当于NOT布尔算符,必须都不满足所有的子schema校验

allOf关键字为例:

必须要满足符合字符串类型且最大长度为5的值

{
  "allOf": [
    { "type": "string" },
    { "maxLength": 5 }
  ]
}
// right
"short" 
// error 字符长度超出5
"too long" 

条件sechma

可以使用if,then,else关键字实现条件逻辑判断,当符合if子schema条件,则对then的子schema条件进行校验,若if子schema条件不通过,则走else子schema条件校验

{
  "type": "object",
  "properties": {
    "street_address": {
      "type": "string"
    },
    "country": {
      "default": "United States of America",
      "enum": ["United States of America", "Canada"]
    }
  },
  "if": {
    "properties": { "country": { "const": "United States of America" } }
  },
  "then": {
    "properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } }
  },
  "else": {
    "properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } }
  }
}
// right
// if的schema验证通过,则校验then的schema,20500 符合 /[0-9]{5}(-[0-9]{4})?/ 正则表达式
{
  "street_address": "1600 Pennsylvania Avenue NW",
  "country": "United States of America",
  "postal_code": "20500"
}
// error
// if的schema验证不通过,则校验else的schema,10000 不符合 /[A-Z][0-9][A-Z] [0-9][A-Z][0-9]/ 正则表达式
{
  "street_address": "24 Sussex Drive",
  "country": "Canada",
  "postal_code": "10000"
}

递归

使用$ref关键字引用自己的子schema片段,实现递归模式,可以用于树形结构的描述

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "$ref递归调用",
  "definitions": {
    "node": {
      "type": "object",
      "properties": {
        "children": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/node"
          }
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "tree": {
      "$ref": "#/definitions/node"
    }
  }
}

以下的JSON结构才能在上述的JSON Schema校验通过

{
  "tree": {
    "children": [
      {
        "children": [
          {
            "children": []
          }
        ]
      }
    ]
  }
}

应用

JSON Schema规范了JSON格式,使JSON的解析控制在一定的范围了,在JSON输入到输出等过程中添加Schema协议的校验,减少了代码程序出错的几率,一定程度上保证了代码的质量。
JSON Schema在公司的内部项目上也有应用,例如raptor活动运营平台JSON Schema可视化组件编辑器,pear配置管理平台使用JSON Schema生成输入表单,在amis开发中通过json配置中台页面等等。可见,JSON Schema在代码开发过程中发挥不可忽视的作用,我们应该加以理解并应用JSON Schema,下面归纳一下JSON Schema一些用途。

1、生成JSON格式可读文档

使用过typescript都应该了解静态类型的好处,代码包含了类型接口声明,相当于文档注释,使代码一目了然,提高了可读性。我们可以基于现有的JSON来生成JSON Schema,快速生成JSON格式规范,相当于一份可读文档,减少了团队之间的沟通理解成本。

通过JSON转换JSON Schema在线工具:
www.jsonschema.net/

2、提供更为准确可靠的mock数据

基于JSON Schema提供多种校验约束条件,可以使用它原生的能力来生成更为准确可靠的mock数据

使用JSON Schema生成mock数据在线工具:
json-schema-faker.js.org/

3、数据校验

基于JSON Schema提供多种校验约束条件,可以定义数据的校验规则,通过JSON Schema进行数据校验,多用于接口请求参数校验,表单校验,和数据校验自动化测试上

JSON Schema校验工具:Ajv

4、基于JSON Schema配置文件渲染UI组件

1

借助vue、react框架组件化理念以及动态渲染组件能力,涌现了许多基于JSON Schema配置文件渲染表单或者组件的库,有效解决通用性组件大量重复使用的场景。通过JSON配置组件乃至页面,能够使代码转化为文件,使数据得以导入导出,便于迁移储存。另外也可以开发可视化编辑器,通过拖拽交互,生成JSON文件,降低开发使用难度。基于这一系列的方案,使开发效率大大提升和降低后续的代码维护。

在vue框架下,vue-json-schema-form提供了表单组件生成工具

vue-json-schema-form 基于JSON Schema的关键字type所定义的类型来渲染对应表单组件,并适配了第三方的UI库

主要架构:

3

渲染流程:

2

参考资料:

Understanding JSON Schema
vue-json-schema-form

欢迎大家留言讨论,祝工作顺利、生活愉快!

我是bigo前端,下期见。