阅读 525

JSON SCHEMA笔记(一)概念与关键字(json schema用途)

在实际业务中,后端存在某些参数极为复杂的接口,这时候可以把所有的参数都用JSON接收。但是,JSON校验就成了一个棘手的问题,手写校验复杂且繁琐。

任何数据都可能有两个验证阶段:

  • 架构级别:json结构可以通过JSON Schema验证

  • 语义级别:json的语义需要转换成实际的业务实体来进行校验

而JSON Schema 是用于验证 JSON 数据结构的强大工具,通过它可以快速验证复杂的JSON结构。JSON Schema本身是用JSON编写的,用于“描述其他数据结构”的声明性格式。

一、基本

1. 相关概念

  • JSON实例:表示数据模型解释文档,根据JSON Schema解释的 JSON 值称为“实例”;用JSON的话说就是value格式、取值相同

    • JSON实例相等:当且仅当两个 JSON 实例属于相同类型且具有相同值时,才称它们相等;

    • 可以将 JSON Schema 与 JSON Schema 数据模型的超集一起使用,其中实例可能在六种 JSON 数据类型中的任何一种之外。

  • JSON Schema:JSON Schema 文档,或简称为 schema,是定义JSON元数据的JSON 文档;JSON元数据通过关键字(keyword)定义了Json数据需要满足的规范,规范包括了成员结构类型约束

注:对象必须具有相同数量的成员,对象中的属性是无序的,无法定义多个具有相同KEY的属性,而仅仅是格式上的差异(缩进、放置逗号、尾随零)无关紧要。
注2:由于一个对象不能有两个具有相同键的属性,因此尝试在单个对象中定义具有相同键的两个属性的 JSON 文档的行为是undefined的。
注3:模式本身可以被解释为一个实例,但应该总是被赋予媒体类型“application/schema+json”而不是“application/schema-instance+json”。“application/schema+json”媒体类型被定义为提供“application/schema-instance+json”提供的片段标识符语法和语义的超集。

2. JSON Schema Documents的组成

  • JSON关键字:应用于实例的对象属性称为关键字或模式关键字

    • identifiers(身份标志):URI

    • assertions(断言):应用于实例,判断状态,产生布尔类型结果

    • annotations(注释)

    • applicators:将一个或多个子模式应用于实例中的特定位置,并组合或修改它们的结果

    • reserved locations:不直接影响结果,但为特定目的预留位置以确保互操作性

  • Boolean JSON Schemas:用于阐明模式作者的意图并促进模式处理优化

    • true:表示空模式{}

    • false:表示模式{ "not": {} }

  • Schema Vocabularies:模式词汇表,或简称为词汇表,是一组关键字、语法和语义;

    • 定义词汇表通常是为了特定目的组织起来的;

    • 可以定义词汇表是必需或可选的

  • Meta-Schemas(元模式):用于描述模式的模式,用于验证JSON模式并指定使用的词汇表

  • Root Schema and Subschemas and Resources(根模式、子模式和资源)

例如:

{
"title": "root", // 文档的根模式
 "items": { // 包含子模式
  "title": "array item"
 }
}复制代码

二、关键字

Json Schema中的常用的关键字可以分为类型关键字、通用关键字以及schema组合

1. 类型关键字

string

相关属性:

  • minLength

  • maxLength

  • pattern

  • format

    • "regex"

    • "json-pointer"

    • "relative-json-pointer"

    • "uri-template"

    • "uri"

    • "uri-reference"

    • "iri"

    • "iri-reference"

    • "ipv4"

    • "ipv6"

    • "hostname"

    • "idn-hostname"

    • "email"

    • "idn-email"

    • "date-time":例如 2018-11-13T20:20:39+00:00

    • "time":例如 20:20:39+00:00

    • "date":例如 2018-11-13

    • Dates and times(日期和时间)

    • Email addresses(邮箱地址)

    • Hostnames(host)

    • IP Addresses(IP地址)

    • Resource identifiers(绝对或相对资源路径)

    • URI template

    • JSON Pointer(json schema 快捷链接)

    • Regular Expressions(正则)

number

  • multipleOf 将数字限定为该属性的倍数,可以为任何整数

  • Range(设置范围):minimumexclusiveMinimummaximumexclusiveMaximum

    • x ≥ minimum

    • x > exclusiveMinimum

    • x ≤ maximum

    • x < exclusiveMaximum

例如:

{
  "type": "number",
  "minimum": 0,
  "maximum": 100,
  "exclusiveMaximum": true
}复制代码

integer (只能表示整数)

object(JSON映射类型)

  • properties(属性键值对)

    • key 属性名称

    • value 对象

  • patternProperties   (如果属性名匹配模式,属性值必须通过特定schema的验证)

  • additionalProperties   默认为true,设置为false表示不允许额外的属性

  • required  定义必须的字段

  • propertyNames  验证属性名

  • minProperties  限制至少有几个属性

  • maxProperties  限制最多有几个属性

例如:

{
  "type": "object",
  "properties": {
    "number": { "type": "number" },
    "street_name": { "type": "string" },
    "street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
  }
}
{
  "type": "object",
  "patternProperties": {
    "^S_": { "type": "string" },
    "^I_": { "type": "integer" }
  }
}
// 允许类型为string的额外属性
{
  "type": "object",
  "properties": {
    "number": { "type": "number" },
    "street_name": { "type": "string" },
    "street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
  },
  "additionalProperties": { "type": "string" }
}

{
  "type": "object",
  "propertyNames": {
    "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
  }
}
//ERR
{
  "001 invalid": "value"
}复制代码

array

  • items

    • 列表:存放同种类型数据

    • 元组:存放不同类型数据

  • additionalItems:默认为true,允许额外类型的项;如果不是元组,则忽略该属性

  • contains:该属性表示包含某种类型即可

  • minItems

  • maxItems

  • uniqueItems 用于保证item唯一

例如:

// 列表
{
  "type": "array",
  "items": {
    "type": "number"
  }
}
// 元组
{
  "type": "array",
  "items": [
    { "type": "number" },
    { "type": "string" },
    { "enum": ["Street", "Avenue", "Boulevard"] },
    { "enum": ["NW", "NE", "SW", "SE"] }
  ]
}复制代码

boolean

布尔类型只匹配两个特殊值:true和false。请注意,架构不接受判定其余值为true或false,例如1和0的值。

 

null

  • 当架构指定空缺类型时,它只有一个可接受的值:null

  • 在json中,null不等同于不存在的东西

2. 通用关键字

JSON Schema包含一些关键字不用于验证,而是用于描述模式;编写JSON Schema的开发人员不一定需要这些“注释”关键字,但鼓励使用这些字段使架构能“自我记录”。

  • title 标题

  • description 描述

  • default 表示默认值

  • examples 示例JSON

  • readOnly 表示不应修改值

  • writeOnly 表示可以设置值

  • $comment 表示注释

  • enum 表示枚举

  • const 常量、限制为单个值

{
  "title": "Match anything",
  "description": "This is a schema that matches anything.",
  "default": "Default value",
  "examples": [
    "Anything",
    4035
  ],
  "readOnly": true,
  "writeOnly": false
}

{
  "enum": ["red", "amber", "green"]
}复制代码

3. Schema 组合

  • allOf(AND):所有条件都对子模式有效、非空数组,每一项都是有效的JSON Schema

  • anyOf(OR):至少有一个条件对子模式有效、非空数组

  • oneOf(XOR):有且只有一个条件对子模式有效、非空数组

  • not(NOT):所有的都不匹配则表示成功

{
  "allOf": [
    { "type": "string" },
    { "maxLength": 5 }
  ]
}

     "short" TRUE
     "too long" FALSE

{
  "anyOf": [
    { "type": "string", "maxLength": 5 },
    { "type": "number", "minimum": 0 }
  ]
}


     "short" TRUE
     "too long" FALSE
     12 TRUE
     -5 FALSE

{
  "oneOf": [
    { "type": "number", "multipleOf": 5 },
    { "type": "number", "multipleOf": 3 }
  ]
}

     10 TRUE
     9 TRUE
     2 FALSE
     15 FALSE

{ "not": { "type": "string" } }
 
     42 TRUE
 
 
 { "key": "value" } TRUE
 
     "I am a string" FALSE复制代码

注:allOf不允许使用additionalProperties

分解模式:子模式的公共部分支持分解,以下的两个模式等效

{
  "oneOf": [
    { "type": "number", "multipleOf": 5 },
    { "type": "number", "multipleOf": 3 }
  ]
}

{
   "type": "number",
   "oneOf": [
     { "multipleOf": 5 },
     { "multipleOf": 3 }
   ]
 }


作者:此间码农
链接:https://juejin.cn/post/7028757292552028167


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐