json schema 關鍵字速查

相關文章:
[1] Understanding JSON Schema
[2] Json Schema 快速入門
[3] Json Schema簡介

1 引言

1.1 背景

json格式中提供如下A(整型)、B(浮點型)、C(布爾)、D(字符串)、E(空)5種基本數據類型(實際整型和浮點型均視作數值型),外加F(對象)、G(數組) 2種複合數據類型。原始的json格式由於本質上就是一堆字符串,所以並沒有對字段值最任何限制(特性類似xml)。實際應用場景中,往往需要對字段取值做限制,比如限制字符串最大長度,數值的上下限,方便解析程序在解析json時,檢驗收到數據的有效性。此時json schema技術(類比xml schema)應運而生!

{

    "A": 1,

    "B": 1.27264,

    "C": true,

    "D": "string",

    "E": null,

    "F": {

        "F_A": 2,

        "F_B": "Hello" 

    },

    "G": [1, 2],

}

json schema 限定數據有效性,以校驗json數據是否合法的技術

1.2 什麼是Json Schema? 

以一個例子來說明:

假設有一個web api,接受一個json請求,返回某個用戶在某個城市關係最近的若干個好友。一個請求的例子如下:

{
   
"city" : "chicago",
   
"number": 20,
   
"user" : {
       
"name":"Alex",
       
"age":20
    }
}

在上面的例子中,web api要求提供city,number,user三個成員,其中city是字符串,number是數值,user是一個對象,又包含了name和age兩個成員。

對於api來說,需要定義什麼樣的請求合法,即什麼樣的Json對於api來說是合法的輸入。這個規範可以通過Json Schema來描述,對應的Json Schema如下。

{
    "type": "object",
    "properties": {
       
"city": { "type": "string" },
        
"number": { "type": "number" },
        
"user": {
           
"type": "object",
           
"properties": {
               
"name" : {"type": "string"},
                
"age" : {"type": "number"}
         
    }                       
     
   }
    }
}

例子可以通過Json Schema Validator來驗證:

所以什麼是Json Schema

Json Schema定義了一套詞彙和規則,這套詞彙和規則用來定義Json元數據,且元數據也是通過Json數據形式表達的。Json元數據定義了Json數據需要滿足的規範,規範包括成員、結構、類型、約束等。

本文後面的部分是簡要介紹Json Schema定義的這些規則,以及如何用這些規則描述規範。

Json Schema定義了一系列關鍵字,元數據通過這些關鍵字來描述Json數據的規範。其中有些關鍵字是通用的;有些關鍵字是針對特定類型的;還有些關鍵字是描述型的,不影響合法性校驗。本文的主要內容就是介紹這些關鍵字的應用。

2 類型關鍵字

首先需要了解的是"type"關鍵字,這個關鍵字定義了Json數據需要滿足的類型要求。"type"關鍵字的用法如下面幾個例子:

{"type":"string"}。規定了Json數據必須是一個字符串,符合要求的數據可以是
"Today is a good day."
"I love you"

{"type" : "object"}。規定了Json數據必須是一個對象,符合要求的數據可以是
{"name" : "Alexander", "age" : 98}
{}

{"type" : "number"}。規定了Json數據必須是一個數值,符合要求的數據可以是。Java Script不區分整數、浮點數,但是Json Schema可以區分。
2
0.5

{"type": "integer"}。要求數據必須是整數。
2

{"type" : "array"}。規定了Json數據必須是一個數組,符合要求的數據可以是
["abc", "cdf"]
[1, 2, 3]
["abc", 25, {"name": "Alexander"} ]
[]

{"type" : "boolean"}。這個Json Schema規定了Json數據必須是一個布爾,只有兩個合法值
true
false

{"type" : "null"}。null類型只有一個合法值
null

3 簡單類型

這部分介紹類型特定的關鍵,包括字符串、數值、布爾、空值幾種基本類型。

3.1 字符串

Json合法的字符串            

"Today is a good day."

對應的Json Schema

{"type": "string"}

可以進一步對字符串做規範要求。字符串長度匹配正則表達式字符串格式

3.1.1 字符串長度

關鍵字: minLength, maxLength

可以對字符串的最小長度、最大長度做規範。

{
   
"type" : "string",
   
"minLength" : 2,
   
"maxLength" : 3,
}

3.1.2 正則表達式

關鍵字: pattern

可以對字符串應滿足的Pattern做規範,Pattern通過正則表達式描述。

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

3.1.3 字符串Format

關鍵字: format

可以通過Json Schema內建的一些類型,對字符串的格式做規範,例如電子郵件、日期、域名等。

{ "type" : "string", "format" : "date", }

Json Schema支持的format包括"date", "time", "date-time", "email", "hostname"等。具體可以參考文檔

3.2 數值

Json Schema數值類型包括"number"和"integer"。number合法的數值可以是

2

0.1

對應的Json Schema爲

{"type": "number"}

如果是integer則只能是整數。"number"和"integer"的類型特定參數相同,可以限制倍數範圍

3.2.1 數值滿足倍數

關鍵字: multipleOf

可以要求數值必須某個特定值的整數倍。例如要求數值必須是10的整數倍。

{
   
"type" : "number",
   
"multipleOf" : 10,
}

3.2.2 數值範圍

關鍵字: minimum, maximum, exclusiveMinimum, exclusiveMaximum

可以限制數值的方位,包括最大值、最小值、開區間最大值、開區間最小值。

要求數值在[0, 100)範圍內。

{
   
"type" : "number",
   
"minimum": 0,
   
"exclusiveMaximum": 100
}

3.3 布爾

布爾類型沒有額外的類型特定參數。

3.4 空值

null類型沒有額外的類型特定參數。

4 複合類型

複合類型可以通過Nest的方式構建複雜的數據結構。包括數組、對象。

4.1 數組

Json數組合法數據的例子

[1, 2, 3]

[1, "abc", {"name" : "alex"}]

[]

Json Schema爲

{"type": "array"}

數組的類型特定參數,可以用來限制成員類型是否允許額外成員最小元素個數最大元素個數是否允許元素重複

4.1.1 數組成員類型

關鍵字: items

可以要求數組內每個成員都是某種類型,通過關鍵字items實現。下面的Schema要求數組內所有元素都是數值,這時關鍵字"items"對應一個嵌套的Json Schema,這個Json Schema定義了每個元素應該滿足的規範。

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

[1, 2, 3]

關鍵字items還可以對應一個數組,這時Json數組內的元素必須與Json Schema內items數組內的每個Schema按位置一一匹配。

{
   
"type": "array",
   
"items": [
    {
       
"type": "number"
    },
    {
       
"type": "string"
    }]
}

[1, "abc"]

4.1.2 數組是否允許額外成員

關鍵字: additionalItems

當使用了items關鍵字,並且items關鍵字對應的是Schema數組,這個限制才起作用。關鍵字additionalItems規定Json數組內的元素,除了一一匹配items數組內的Schema外,是否還允許多餘的元組。當additionalItems爲true時,允許額外元素。

{
   
"type": "array",
   
"items": [
    {
       
"type": "number"
    },
    {
       
"type": "string"
    }],
   
"additionalItems" : true
}

[1, "abc", "x"]

4.1.3 數組元素個數

關鍵字: minItems, maxItems

可以限制數組內元素的個數。

{
   
"type": "array",
   
"items": {
       
"type": "number"
    },
   
"minItems" : 5,
   
"maxItems" : 10
}

[1,2,3,4,5,6]

4.1.4 數組內元素是否必須唯一

關鍵字: uniqueItems

規定數組內的元素是否必須唯一。

{
   
"type": "array",
   
"items": {
       
"type": "number"
    },
   
"uniqueItems" : true
}

[1,2,3,4,5]

4.2 對象

Json對象是最常見的Json數據類型,合法的數據可以是

{
   
"name": "Froid",
   
"age" : 26,
   
"address" : {
       
"city" : "New York",
       
"country" : "USA"
    }
}

就對象類型而言,最基本的類型限制Schema是

{"type" : "object"}

然而,除了類型外,我們通常需要對其成員做進一步約定。對象的類型特定關鍵字,大多是爲此目的服務的。

4.2.1 成員的Schema

關鍵字:properties

規定對象各成原所應遵循的Schema。

{
   
"type": "object",     
   
"properties": {     
       
"name": {"type" : "string"},
       
"age" : {"type" : "integer"},
       
"address" : {
           
"type" : "object",
           
"properties" : {
               
"city" : {"type" : "string"},
               
"country" : {"type" : "string"}
            }
        }
    }
}

對於上例中的Schema,合法的data是

{
   
"name": "Froid",
   
"age" : 26,
   
"address" : {
       
"city" : "New York",
       
"country" : "USA"
    }
}

properties關鍵字的內容是一個key/value結構的字典,其key對應Json數據中的key,其value是一個嵌套的Json Schema。表示Json數據中key對應的值所應遵守的Json Schema。在上面的例子中,"name"對應的Schema是{"type" : "string"},表示"name"的值必須是一個字符串。在Json數據中,對象可以嵌套,同樣在Json Schema中也可以嵌套。如"address"字段,在Json Schema中它的內容是一個嵌套的object類型的Json Schema。

4.2.2 批量定義成員Schema

關鍵字:patternProperties

與properties一樣,但是key通過正則表達式匹配屬性名。
{
   
"type": "object",
   
"patternProperties": {
       
"^S_": { "type": "string" },
       
"^I_": { "type": "integer" }
    }
}

{"S_1" : "abc"}

{"S_1" : "abc", "I_3" : 1}

4.2.3 必須出現的成員

關鍵字:required

!規定哪些對象成員是必須的,其他的成員則可選的

{
   
"type": "object",     
   
"properties": {     
       
"name": {"type" : "string"},
       
"age" : {"type" : "integer"},
    },
   
"required" : ["name"]
}

上例中"name"成員是必須的,因此合法的數據可以是

{"name" : "mary", "age" : 26}

{"name" : "mary"}

但缺少"name"則是非法的

{"age" : 26}

4.2.4 成員依賴關係

關鍵字:dependencies

規定某些成員的依賴成員,不能在依賴成員缺席的情況下單獨出現,屬於數據完整性方面的約束。

{
   
"type": "object",
   
"dependencies": {
       
"credit_card": ["billing_address"]
    }
}

dependencies也是一個字典結構,key是Json數據的屬性名,value是一個數組,數組內也是Json數據的屬性名,表示key必須依賴的其他屬性。

上面Json Schema合法的數據可以是

{}

{"billing_address" : "abc"}

但如果有"credit_card"屬性,則"billing_address" 屬性不能缺席。下面的數據是非法的

{"credit_card": "7389301761239089"}

4.2.5 是否允許額外屬性

關鍵字:additionaProperties

規定object類型是否允許出現不在properties中規定的屬性,只能取true/false。

{
   
"type": "object",     
   
"properties": {     
       
"name": {"type" : "string"},
       
"age" : {"type" : "integer"},
    },
   
"required" : ["name"],
   
"additionalProperties" : false
}

上例中規定對象不能有"name"和"age"之外的成員。合法的數據

{"name" : "mary"}

{"name" : "mary", "age" : 26}

非法的數據

{"name" : "mary", "phone" : ""84893948}

4.2.6 屬性個數的限制

關鍵字:minProperties, maxProperties

規定最少、最多有幾個屬性成員。
{
   
"type": "object",
   
"minProperties": 2,
   
"maxProperties": 3
}

{"name" : "mary", "age" : 26}

{"name" : "mary", "age" : 26, "phone" : "37839233"}

5 邏輯組合

關鍵字:allOf, anyOf, oneOf, not

從關鍵字名字可以看出其含義,滿足所有、滿足任意、滿足一個。前三個關鍵字的使用形式是一致的,以allOf爲例說明其形式。

{
   
"allOf" : [
        Schema1,
        Schema2,
        ...
    ]
}

其中,"allOf"的內容是一個數組,數組內的成員都是內嵌的Json Schema。上例Schema1、Schema2都是內嵌的Json Schema。整個Schema表示當前Json數據,需要同時滿足Schema1、Schema2,。

5.1 allOf

滿足allOf數組中的所有Json Schema。

{
   
"allOf" : [
        Schema1,
        Schema2,
        ...
    ]
}

需要注意,不論在內嵌的Schema裏還是外部的Schema裏,都不應該使"additionalProperties"爲false。否則可能會生成任何數據都無法滿足的矛盾Schema。

可以用來實現類似“繼承”的關係,例如我們定義了一個Schema_base,如果想要對其進行進一步修飾,可以這樣來實現。

{
   
"allOf" : [
        Schema_base
    ]
   
"properties" : {
       
"other_pro1" : {"type" : "string"},
       
"other_pro2" : {"type" : "string"}
    },
   
"required" : ["other_pro1", "other_pro2"]
}

Json數據既需要滿足Schema_base,又要具備屬性"other_pro1"、"other_pro2"。

5.2 anyOf

滿足anyOf數組中的任意個Schema。

{
   
"anyOf" : [
        Schema1,
        Schema2,
        ...
    ]
}

Json數據需要滿足Schema1、Schema2中的一個或多個。

5.3 oneOf

滿足且進滿足oneOf數組中的一個Schema,這也是與anyOf的區別。

{
   
"oneOf" : [
        Schema1,
        Schema2,
        ...
    ]
}

5.4 not

這個關鍵字不嚴格規定Json數據應滿足什麼要求,它告訴Json不能滿足not所對應的Schema。

{
   
"not" : {"type" : "string"}
}

只要不是string類型的都Json數據都可以。

6 複雜結構

對複雜結構的支持包括定義和引用。可以將相同的結構定義成一個“類型”,需要使用該“類型”時,可以通過其路徑或id來引用。

6.1 定義

關鍵字:無

定義一個類型,並不需要特殊的關鍵字。通常的習慣是在root節點的definations下面,定義需要多次引用的schema。definations是一個json對象,key是想要定義的“類型”的名稱,value是一個json schema。

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

    "type": "object",
   
"properties": {
       
"billing_address": { "$ref": "#/definitions/address" },
       
"shipping_address": { "$ref": "#/definitions/address" }
    }
}

上例中定義了一個address的schema,並且在兩個地方引用了它,#/definitions/address表示從根節點開始的路徑。

6.2 id>∗∗關鍵字:id>∗∗關鍵字:id**

可以在上面的定義中加入id屬性,這樣可以通過id屬性,這樣可以通過id屬性的值對該schema進行引用,而不需要完整的路徑。

...
    "address": {
           
"type": "object",
           
"$id" : "address",
           
"properties": {
               
"street_address": { "type": "string" },
               
"city":           { "type": "string" },
               
"state":          { "type": "string" }
            },
           
"required": ["street_address", "city", "state"]
        }

...

6.3 引用

關鍵字:$ref

關鍵字$ref可以用在任何需要使用json schema的地方。如上例中,billing_address的value應該是一個json schema,通過一個$ref替代了。

$ref的value,是該schema的定義在json中的路徑,以#開頭代表根節點。

{
   
"properties": {
       
"billing_address": { "$ref": "#/definitions/address" },
       
"shipping_address": { "$ref": "#/definitions/address" }
    }
}

如果schema定義了$id屬性,也可以通過該屬性的值進行引用。

{
   
"properties": {
       
"billing_address": { "$ref": "#address" },
       
"shipping_address": { "$ref": "#address" }
    }
}

7 通用關鍵字

通用關鍵字可以在任何json schema中出現,有些影響合法性校驗,有些只是描述作用,不影響合法性校驗。

7.1 enum

關鍵字:enum

可以在任何json schema中出現,其value是一個list,表示json數據的取值只能是list中的某個。
{
   
"type": "string",
   
"enum": ["red", "amber", "green"]
}

上例的schema規定數據只能是一個string,且只能是"red"、"amber"、"green"之一。

7.2 metadata

關鍵字:titledescriptiondefaultexample

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

只作爲描述作用,不影響對數據的校驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章