JSON Schema是一个用于验证JSON数据结构的强大工具, 我查看并学习了JSON Schema的官方文档, 做了详细的记录, 分享一下。

  我们可以使用JSON Schema在后续做接口测试中做详细的数据值的校验, 数据类型校验, json数据结构的校验。

jsonschema用以标注和验证JSON文档的元数据的文档

官方文档地址jsonschema

简单实例

有一个简单的json数据, 根据json数据格式编写jsonschema, 然后校验json数据每个字段是否是规定类型。

import jsonschema
 
json_data = [
{
  'pm10': 24,
  'city': '珠海',
  'time': '2016-10-23 13:00:00'
},
{
  'pm10': 24,
  'city': '深圳',
  'time': '2016-10-21 13:00:00'
},
{
  'pm10': '21',
  'city': '广州',
  'time': '2016-10-23 13:00:00'
}
]
 
json_schema = {
  'type': 'array',
  'items': {
    'type': 'object',
    'properties': {
      'pm10': {
        'type': 'number',
      },
      'city': {
        'type': 'string',
        'enum': ['珠海', '深圳']
      },
      'time': {
        'type': 'string'
      }
    }
  }
}
try:
  jsonschema.validate(json_data, json_schema)
except jsonschema.ValidationError as ex:
  msg = ex
  print(ex)

type关键字

type关键字是json模式的基础, 指定架构的数据类型。 
JSON Schema的核心定义了以下基本类型:

  • string
  • Numeric types
  • object
  • array
  • boolean
  • null

这些类型在Python中对应的类型如下, 下表将JavaScript类型的名称映射到Python的相关类型:

JavaScript Python
string string
number int/float
object dict
array list
boolean bool
null none

type关键字可以是一个字符串或数组:

  • 如果它是一个字符串, 那么它是上面一个基本能类型的名称
  • 如果它是一个数组, 它必须是一个字符串数组, 其中每个字符串是其中一个基本类型的名称, 每个元素都是唯一的。在这种情况下, 如果json代码段与任何给定类型匹配,则改代码段有效。

以下做个type关键字的简单示例:

{“type”: “number”}

定义某个字段类型是number, 如果是 40, 43.0这样是校验通过的 
如果是”43”, 包含数字的字符串这样是无法校验通过的.

{“type”: [“number”, ‘string’]}

定义某个字段类型是number或string中一种 
如果是43, 或者 “我和你” 这样是校验通过的 
如果是[43, “我和你”], 这样是不通过的, 因为不接受结构化数据类型。

object关键字

在Python中, 对象对应的类型是dict类型。

属性 properties

使用properties关键字定义对象上的属性(键值对)。 
例如, 我们要为由数字, 街道名称和街道类型组成的地址定义一个简单的模式

{
  “type” : “object” ,
  “properties” : {
    “number” : { “type” : “number” },
    “street_name” : { “type” : “string” },
    “street_type” : {
         “type” : “string” ,
         “enum” : [ “Street” , “Avenue” , “Boulevard” ]
    }
  }
}

必需属性

默认情况下,properties不需要由关键字定义的属性。但是,可以使用required关键字提供所需属性的列表。

required关键字接受一个或多个字符串的数组。每个字符串必须是唯一的。

在以下定义用户记录的示例模式中,我们要求每个用户都有一个名称和电子邮件地址,但我们不介意他们是否提供了他们的地址或电话号码:

{
  “type” : “object” ,
  “properties” : {
    “name” : { “type” : “string” },
    “email” : { “type” : “string” },
    “address” : { “type” : “string” },
    “telephone” : { “type” : “string” }
  },
  “required” : [ “name” , “email”]
}

大小

可以使用minProperties和maxProperties关键字限制对象上的属性数 。这些中的每一个都必须是非负整数。

{
  “type” : “object” ,
  “minProperties” : 2 ,
  “maxProperties” : 3
}

数组属性

数组用于有序元素。 
在Python中, array类似于 list或tuple类型,具体取决于用法。 
例如: [1,2,3,4,5] 
[2, ‘dd’]

items

数组的元素可能是任何东西, 但是,根据某些模式验证数组的项通常很有用。这里使用items和additionalItems关键字完成。

在JSON中, 通常使用两种方式的数据

  • 列表验证: 任意长度的序列, 其中每个元素匹配相同的模式
  • 元组验证: 一个固定长度的序列,其中每个项目可能具有不同的模式, 在此用法中, 每个项目的索引(位置)对于如何解释值是有意义的,例如Python的tuple。
List validation

列表验证对于任意长度的数组非常有用, 其中每个项都匹配相同的模式, 对于此类数组, 将items关键字设置为单个模式, 用该模式来验证数组中的所有项。

注意: 这时items是单个模式, additionalItems关键字没有意义, 不应该使用它。 
例如下面的事例中我们定义数组中每个项都是一个数字

{
  “type” : “array” ,
  "items": {
    "type": "number"
  }
}

如果是[1,2,3,4,5], pass 
如果是[1,2,3,’5’, 6] , false 
如果是[], pass

Tuple validation

当数组是项目集合时, 就需要元组验证。其中每个项目都有不同的模式, 并且每个项目的序数索引是有意义的。

例如: 街道地址这样表示

1600 Pennsylvania Avenue NW 
就有4中type 
[number, streent_name, street_type, direction]

每个字段都有不同的架构

  • number: 地址编号, 必须是数字
  • street_name: 街道的名称, 必须是字符串
  • street_type: 街道的类型, 应该是一组固定值的字符串
  • direction: 地址的位置, 应该是来自不同值集的字符串

为此我们将items关键字设置成一个数组, 其中每个项目都是一个与文档数组的每个索引相对应的模式, 也就是一个数组, 第一个元素模式验证输入数组的第一个元素. 第二个元素模式验证输入数组的第二个元素, 等等

示例:

{
  “type” : “array” ,
  “items” : [
    {
      “type” : “number”
    },
    {
      “type” : “string”
    },
    {
      “type” : “string” ,
      “enum” : [ “Street” “ , ”Avenue“ , ”Boulevard“ ]
    },
    {
      ”type“ : ”string“ ,
      ”enum“ : [ ”NW“ , ”NE“ , “SW” , “SE” ]
    }
  ]
}

如果是[1600, “宾夕法尼亚”, ‘Street’, “NW”], pass 
如果是[10,’等等’, ‘等等’], false 
并且在默认情况下, 添加其他项目也可以: 
[ 1600 , “宾夕法尼亚州” , “Street” , “NW” , “华盛顿” ]

additionalItems关键字控制是否有效有超出了在架构中定义的数组的其他项目,如果设置为false, 则会不允许数组中的额外项。

长度

可以使用minItems和 maxItems关键字指定数组的长度。每个关键字的值必须是非负数。无论是进行List验证还是Tuple验证,这些关键字都有效。 
示例:

{
  “type” : “array” ,
  “minItems” : 2 ,
  “maxItems” : 3
}
唯一性

使用uniqueItems关键字设置为true, 则数组中的每个项都是唯一的。

通用关键字

元数据

json模式包含几个关键字, titledescriptiondefault, 不严格用来校验格式,但用来描述模式的一部分。 
在title和description管家你必须是字符串

枚举值

enum关键字用于限制值, 以一个固定的一组值, 它必须是一个必须包含一个元素的数组,其中每个元素都是唯一的。


  ‘type’ : ‘string’, 
  ‘enum’: [‘red’, ‘green’] 
}

如果检验字段的值在枚举中是通过的, 如果不是无法校验通过。

组合模式

JSON Schema包含一些用于将模式组合在一起的关键字,这并不意味着组合来自多个文件或JSON树的模式, 尽管这些工具有助于实现这一点,并在结构化复杂模式中进行了描述。

例如, 在以下的模式, anyOf关键字用于表示给定值可能对任何给定的子模式有效。第一个子模式需要一个最大长度为5的字符串。第二个子模式需要一个最小值为0的数字。只要一个值对这些模式中的任何一个进行验证,它就被认为整个组合模式有效。

{ ‘anyOf’: [ {‘type’: ‘string’, ‘maxLength’: 5}, {‘type’:’string’, ‘minimum’: 0 }]}

用于组合模式的关键字是:

  • allOf: 必须对所有子模式有效
  • anyOf: 必须对任何子模式有效(一个或多个)
  • oneOf: 必须仅对其中一个子模式有效

anyOf

要进行验证anyOf,给定数据必须对任何(一个或多个)给定子模式有效。

{
  “anyOf” : [
    { “type” : “string” },
    { “type” : “number” }
  ]
}

如果是 “您好”, pass 
如果是 33, pass 
如果是 [‘ddd’, 33], false

oneOf

要进行验证oneOf,给定数据必须仅对其中一个给定子模式有效。

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

如果是5的倍数, pass 
如果是3的倍数, pass 
如果是5和3的倍数, false

allOf

要进行验证allOf,给定数据必须对所有给定的子模式有效。

{
  “allOf” : [
    { “type” : “string” },
    { “maxLength” : 5 }
  ]
}

$schema关键字

该$schema关键字用于声明JSON片段实际上是JSON模式的一部分。它还声明了针对该模式编写的JSON Schema标准的哪个版本。

建议所有JSON模式都有一个$schema条目,该条目必须位于根目录下。因此,大多数情况下,您需要在架构的根目录下:

“$ schema” : “http://json-schema.org/schema#

正则表达式

该模式和模式属性关键字使用正则表达式来表示约束。使用的正则表达式语法来自JavaScript(具体为ECMA 262)。但是,并未广泛支持该完整语法,因此建议您坚持使用下述语法的子集。

  • 单个unicode字符(下面的特殊字符除外)与自身匹配。
  • ^:仅匹配字符串的开头。
  • $:仅匹配字符串的末尾。
  • (…):将一系列正则表达式分组到单个正则表达式中。
  • |:匹配|符号前面或后面的正则表达式。
  • [abc]:匹配方括号内的任何字符。
  • [a-z]:匹配字符范围。
  • [^abc]:匹配未列出的任何字符。
  • [^a-z]:匹配范围之外的任何字符。
  • +:匹配前一个正则表达式的一个或多个重复。
  • *:匹配前面正则表达式的零次或多次重复。
  • ?:匹配前一个正则表达式的零次或一次重复。
  • +?,?,??:的,+和?预选赛都是贪婪的; 它们匹配尽可能多的文本。有时这种行为是不可取的,您希望匹配尽可能少的字符。
  • {x}:完全x匹配前面正则表达式的出现次数。
  • {x,y}:匹配前面正则表达式的至少x和最y多次出现。
  • {x,}:匹配x前面正则表达式的出现次数或更多。
  • {x}?,{x,y}?,{x,}?:上述表达式的惰性版本。

示例:

{
  “type” : “string” ,
  “pattern” : “^(\\([0-9] {3} \\))?[0-9]{3}-[0-9] {4} $ “
}

如果是 “555-1212”, pass 
如果是“(888)555-1212” , pass 
如果是“(888)555-1212分机532” , false

构建复杂的模式

重用

有些模式可能是在几个地方都是通用的, 如果每次都重写会使模式更加冗长,以后更新也会很复杂, 我们可以用重用的方式来做。 
例如: 
定义客户记录, 每个客户都有可能同时拥有送货地址和账单地址, 地址总是相同的, 有街道地址, 城市, 州名。

定义地址模式:

{

  “type” : “object” ,

  “properties” : {
    “street_address” : { “type” : “string” },
    “city” : { “type” : “string” },
    “state” : { “type” : “string” }
  },
  “required” : [ “street_address” , “city” ,“state” ]
}

我们重用上面的模式, 将其放在父模式下, 名为definitions:

{
  “definitions” : {
    “address” : {
      “type” : “object” ,
      “properties” : {
        “street_address” :{“type” :“string”},
        “city” : { “type” : “string” },
        “state” : { “type” : “string” }
      },
    “required” :[“street_address” ,“city”,“州”]
    }
  }
}

然后我们使用$ref关键字从其他地方引用此架构片段, 指向此模块的位置

{ “$ ref” : “#/ definitions / address” }

值 $ref 是一个名为 JSON Pointer的格式的字符串。

‘#’ 引用当前文档, ‘/’ 遍历文档中对象中的键, 因此 
“#/ definitions / address” 意味着:

  1. 转到文档的根目录
  2. 找到秘钥的值”definitions”
  3. 在该对象中, 找到键的值”address”

$ref也可以是相对或绝对的URI, 例如:

{ “$ ref” : “definitions.json#/ address” }

JsonSchema使用详解的更多相关文章

  1. Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解

    Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全   Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  5. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  6. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  7. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  8. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  9. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

随机推荐

  1. UVa 437 The Tower of Babylon(DP 最长条件子序列)

     题意  给你n种长方体  每种都有无穷个  当一个长方体的长和宽都小于还有一个时  这个长方体能够放在还有一个上面  要求输出这样累积起来的最大高度 由于每一个长方体都有3种放法  比較不好控制 ...

  2. Guice 学习(七)常量和属性的注入( Constant and Property Inject)

    1.常量注入方式 package com.guice.ConstantInjectDemo; import com.google.inject.Binder; import com.google.in ...

  3. Android--点击EditText的时候弹出软键盘,点击EditText之外空白处软键盘消失

    在android中点击EditText的时候会弹出软键盘,但当我们输入完毕或者想隐藏软键盘时,我们可以点击软键盘上的隐藏按钮,这种方法固然可行,但是为了提高用户体验,我们常常要实现这种功能:当输入完毕 ...

  4. Cocos2d-x教程(35)-三维拾取Ray-AABB碰撞检測算法

    欢迎增加Cocos2d-x 交流群:193411763 转载时请注明原文出处 :http://blog.csdn.net/u012945598/article/details/39927911 --- ...

  5. 【.net项目中。。】.net一般处理程序使用方法

    1.基本原理图 IsReusable属性用来表示在IHttpHandlerFactory对象创建IHttpHandler的时候是否能够将这个Handler存入池中以便重用. 一般处理程序(HttpHa ...

  6. WebStorm初次使用

    1. ctrl + / : 单行注释2. ctrl + shift + / : 块注释 3:展开当前函数代码:Ctrl+“+”,收起当前代码:Ctrl+“-” 4:全局查找: Ctrl+Shift+F ...

  7. IntelliJ IDEA 、genymotion模拟器、Android开发环境搭建

    首先打开IDEA,看到该界面,如果没有该界面,请在User/用户名/IntelliJIDEAProjects/下删除所有项目文件夹.然后重启IDEA即可看到 接着开始配置jdk和sdk 然后在Proj ...

  8. Hibernate二次学习一----------Hibernate简单搭建

    因为博客园自带的markdown不太好用,因此所有markdown笔记都使用cmd_markdown发布 Hibernate二次学习一----------Hibernate简单搭建: https:// ...

  9. 堆排序算法的java实现

         堆积排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素.堆排序是不稳定的排序方法,辅助空间为O(1), 最坏时间复杂度为O ...

  10. iOS tableView Section圆角方案

    给tableView的section设置圆角 首先给让cell左右偏移一点的距离,通过重写cell的setframe方法来实现 -(void)setFrame:(CGRect)frame{ CGFlo ...