Python module - jsonschema Part 2
Posted on Mar 23, 2018 in Python 模組/套件推薦 by Amo Chen ‐ 4 min read
本文為 Python module - jsonchema 一系列教學文:
上一篇 Python module - jsonschema Part 1 中,介紹了 JSON Schema 的 6 種資料型別與驗證 JSON Schema 的方法。
本篇將會更進一步介紹幾種型別( number
, string
, array
, object
)更複雜的用法。
整數(integer)型別
number
包含任意正負數與小數,如果 JSON shema 要定義只接受整數的話,可以把 type
指定為 integer
,例如以下範例用 integer
型別驗證帶有小數點的數字就會驗證失敗:
from jsonschema import validate
schema = {'type': 'integer'}
# would raise exception
validate(123.123, schema)
執行結果:
ValidationError: 123.123 is not of type 'integer'
Failed validating 'type' in schema:
{'type': 'integer'}
On instance:
123.123
限定數值範圍
JSON Schema 能夠限定數值的範圍,其關鍵字有 minimum
maximum
exclusiveMinimum
exclusiveMaximum
。
以下範例為限定數值只能在 1 至 10 之間(包含 1 與 10) :
schema = {
'type': 'number',
'minimum': 1,
'maximum': 10
}
如果要不包含 1 與 10 ,則可以再加上 exclusiveMinimum
exclusiveMaximum
2 個關鍵字,例如以下範例,帶入 1 或 10 都會無法通過驗證:
schema = {
'type': 'number',
'minimum': 1,
'exclusiveMinimum': True,
'maximum': 10,
'exclusiveMaximum': True,
}
限定字串(string)長度
預設 string
型別並沒有字串長度限制,但一般實際使用上字串會有長度限制,例如留言板的留言不能超過 1024 字,最少要 1 個字,我們可以在 JSON Schema 上加上限制字串長度:
shema = {
'type': 'string',
'minLength': 1,
'maxLength': 1024,
}
上述的範例即是使用 minLength
與 maxLength
限制字串的最小與最長長度。
字串的正規表示式
利用正規表示式驗證字串也是很常見的方式, JSON schema 也同樣支援正規表示式的用法,例如限制使用者帳號只能輸入英文與數字:
schema = {
'type': 'sting',
'pattern': '^[a-zA-Z0-9]+$',
}
正規表示式的關鍵字是 pattern
,正規表示式的更詳細語法可以參閱 Regular Expressions 。
內建的字串格式
Python 的 jsonschema 套件也實作 JSON Schema 中規範的幾種格式,例如 date-time
email
等,可以多加利用。以下為使用 format
關鍵字驗證 email 的範例:
import jsonschema
schema = {
'type': 'string',
'format': 'email',
}
jsonschema.validate(
'[email protected]',
schema,
format_checker=jsonschema.FormatChecker()
)
上述範例中的 format_checker=jsonschema.FormatChecker()
是必須的,如果沒有使用該參數, jsonschema 套件就只會檢查資料是否為 string
型別而已。
而 jsonschema 套件也提供客製化 FormatChecker()
的方法,詳情可以參閱 Validating Formats ,相關支援的 format
也可以在該文件中找到。
限定 array
的長度
array
型別預設也沒有長度限制,一般使用上也會有長度的限制,例如月份最多就是 12 個月,因此可以透過 minItems
或 maxItems
2 個關鍵字為 array
加上長度的最小或最長限制:
schema = {
'type': 'array',
'minItems': 1,
'maxItems': 12,
}
限定 array
內的元素不可重複
如果要限定 array
內的元素不可重複,只需要加上 'uniqueItems': True
即可。
schema = {
'type': 'array',
'uniqueItems': True
}
p.s. []
空 array
也會通過驗證
指定 array
內的元素型別
array
提供 items
關鍵字,可以讓我們指定每一個元素的型別,例如指定 array
內的每個元素都必須是 string
:
schema = {
'type': 'array',
'items': {
'type': 'string',
}
}
# would pass
validate(['a', 'b', 'c'], schema)
# would raise exception
validate(['a', 2, 'c'], schema)
執行結果:
ValidationError: 2 is not of type 'string'
Failed validating 'type' in schema['items']:
{'type': 'string'}
On instance[1]:
2
上述範例中 validate(['a', 'b', 'c'], schema)
會通過驗證,而 validate(['a', 2, 'c'], schema)
則是無法通過驗證,原因在於其中一個元素 2 不是 string
型別。
如果陣列內的每一個元素型別不一樣,可以使用 Tuple validation 按照次序分別指定每個元素的型別:
schema = {
'type': 'array',
'minItems': 3,
'maxItems': 3,
'items': [
{'type': 'string'},
{'type': 'number'},
{'type': 'integer'}
]
}
上述範例就必須代入長度為 3 且元素依序分別為 string
number
integer
的型別(例如: ['a', 1.1, 1]
)才能通過驗證,
限定 object
的屬性( Properties
)
object
預設並沒有限定屬性(property),因此只要是 object
都會通過驗證,但一般使用 object
時都會有特定的屬性,例如存放使用者資料的 object
必須有 name , gender , email 3 個屬性,其 JSON Schema 會如以下範例:
schema = {
'type': 'object',
'properties': {
'name': {'type': 'string'},
'gender': {'type': 'string'},
'email': {'type': 'string'},
},
'required': [
'name',
'gender',
'email'
]
}
上述範例用 properties
關鍵字指定 object
內的屬性有 name, gender, email 3 個,但因為預設這些 properties 都是 optional 的,因此額外加上 required
關鍵字,指定 name, gender, email 都是必要屬性,只要 object
資料內沒有這些屬性就會驗證失敗,例如以下少了 email 的 object 會驗證失敗:
# would pass
validate(
{
'name': 'foo',
'gender': 'male',
'email': '[email protected]'
},
schema
)
# would raise exception
validate(
{
'name': 'foo',
'gender': 'male'
},
schema
)
此外,假設屬性都滿足 JSON Schema 的設定時,如果資料內有多餘的屬性也會通過驗證,例如上述範例除了 name, gender, email 如果額外加上任意屬性也會通過驗證:
# would pass
validate(
{
'name': 'foo',
'gender': 'male',
'email': '[email protected]',
'account': 'bar',
},
schema
)
如果要將 object
內存在額外屬性視為格式錯誤的話,可以加上 'additionalProperties': False
讓額外的屬性不被允許。
The
additionalProperties
keyword is used to control the handling of extra stuff, that is, properties whose names are not listed in the properties keyword. By default any additional properties are allowed.
因此上述的 scheam 會變成:
schema = {
'type': 'object',
'properties': {
'name': {'type': 'string'},
'gender': {'type': 'string'},
'email': {'type': 'string'},
},
'required': [
'name',
'gender',
'email'
],
'additionalProperties': False,
}
小結
本篇介紹 number
, string
, array
, object
幾種型別較複雜的用法,下一篇將介紹如何進一步同時混用多種型別,以驗證更加複雜的 JSON 資料格式。
References
https://spacetelescope.github.io/understanding-json-schema/