Python module - jsonschema Part 1

Posted on  Mar 20, 2018  in  Python 模組/套件推薦  by  Amo Chen  ‐ 3 min read

本文為 Python module - jsonchema 一系列教學文:

JSON 目前資料交換格式的主流之一,然而如果要在程式中驗證 JSON 資料的格式是否正確,就需要花費一些心力撰寫驗證的程式碼。所幸現在有 JSON Schema 可以讓驗證 JSON 格式簡單化,如果是以 JSON 作為資料交換格式的 API ,可以考慮使用 JSON Schema 進行驗證。

JSON Schema is a vocabulary that allows you to annotate and validate JSON documents.

本文為 Python 的 jsonschema 套件與驗證 JSON 格式的相關教學。

目前 JSON Schema 仍在草稿階段(draft-07),詳情請參閱 Specification 。而必須注意的是本文所使用的 python jsonschema 模組只支援 draft-03draft-4 2 種版本,因此有些較新的語法是不支援的。

本文環境

  • Python 3.5
  • jsonschema 2.6.0

安裝 jsonschema

$ pip install jsonschema

Hello, jsonschema!

Python 的 jsonschema 模組驗證的是由 Python 資料型別組成的資料,並非 JSON 字串,如果想對 JSON 字串進行驗證,就必須先用 json.loads() 轉換成 Python 的資料型別。

先以範例了解 JSON Schema 的概觀,假設有一個登入的 API 以 JSON 作為交換格式,該 JSON 格式中必須包含 usernamepassword 作為登入之用,如果轉換成 Python 的 dictionary 就會長得像這樣: {'username': 'foobar', 'password': '123456'} ,那麼我們可以針對這格式定義一個 schema 進行格式驗證。

以下是含有 usernamepassword 2 個屬性的 schema ,接著以 validate() 對一個 Python dictionary 進行格式驗證的範例。

from jsonschema import validate
schema = {
    'type': 'object',
    'properties': {
        'username': {
            'type': 'string',
            'minLength': 6,
        },
        'password': {
            'type': 'string',
            'minLength': 8,
        },
    }
}

validate({'username': 'foobar', 'password': '123456'}, schema)

執行結果:

ValidationError: '123456' is too short

Failed validating 'minLength' in schema['properties']['password']:
    {'minLength': 8, 'type': 'string'}

On instance['password']:
    '123456'

從執行結果可以知道 {'username': 'foobar', 'password': '123456'} 驗證沒通過(原因在於 password 長度限制至少為 8 碼)。

透過上述範例,已經能夠使我們了解 jsonchema 如何驗證資料格式,後續將會更詳細地介紹如何定義 JSON Schema 。

Primitive Types

第 1 個範例中的 schema 的 type 關鍵字指的是資料是何種型別,定義一個 JSON Shema 就是在組合這些型別。

The type keyword is fundamental to JSON Schema. It specifies the data type for a schema.

而 JSON Schema 目前定義 6 種資料型別,每 1 種都可以對應回 Python 的資料型別,如下表所示:

| JSON Schema | Python              |
|-----------------------------------|
| object      | dict                |
| array       | list, tuple         |
| string      | str                 |
| number      | int, float, decimal |
| boolean     | bool                |
| null        | None                |

null

null 是最簡單的 type ,它對應到的只有 None

驗證格式時,除了 None 之外的任何 type 都會驗證失敗,以下是範例:

from jsonschema import validate

schema = {'type': 'null'}

# would raise exception
validate(123, schema)

執行結果:

ValidationError: 123 is not of type 'null'

Failed validating 'type' in schema:
    {'type': 'null'}

On instance:
    123

上述範例只要把 123 換成 None 就會通過驗證了。

boolean

boolean 對應到 Python 的 True False ,只要是這 2 個值之外的都會驗證失敗。

schema = {'type': 'boolean'}

# would raise exception
validate(None, schema)

執行結果:

ValidationError: None is not of type 'boolean'

Failed validating 'type' in schema:
    {'type': 'boolean'}

On instance:
    None

同樣地,只要將上述範例中的 None 換為 True 或是 False 即可通過驗證。

number

number 對應的是 Python 的 int float decimal ,如果把字串丟進去驗證就會驗證失敗。

範例:

schema = {'type': 'number'}

# would raise exception
validate('123', schema)

執行結果:

ValidationError: '123' is not of type 'number'

Failed validating 'type' in schema:
    {'type': 'number'}

On instance:
    '123'

這時候只要把 '123' 換成 123 就會正確了。

string

string 對應的是 Python 的 str ,連空字串 '' 也屬於合法的字串。

範例:

schema = {'type': 'string'}

# would pass
validate('', schema)

上述範例會通過驗證,如果放進非字串的值,則會驗證失敗。

array

array 對應的是 Python 的 list tuple ,連空的 list tuple 也屬合法。

schema = {'type': 'array'}

# would pass
validate([1, 2], schema)

上述範例同樣會通過驗證,如果 [1, 2] 改為非 listtuple 的值,則會驗證失敗。

object

object 相當於 Python 的 dict (也就是字典),空的 dict 也屬合法。

schema = {'type': 'object'}

# would pass
validate({'foo': 'bar'}, schema)

上述範例代入了 dict {'foo': 'bar'} ,所以通過 JSON Schema 的驗證,可以試著代入非 dict 型別的值,看看會發生何事。

小結

認識 6 種 JSON Schema 的資料型別之後,至此對 JSON Schema 應已有基礎的認識。

下一篇將會介紹如何利用此 6 種型態組合 JSON Schema 進行複雜的 JSON 格式驗證。

References

http://json-schema.org/

https://spacetelescope.github.io/understanding-json-schema/index.html

追蹤新知

看完這篇文章了嗎?還意猶未盡的話,追蹤粉絲專頁吧!

我們每天至少分享 1 篇文章/新聞或者實用的軟體/工具,讓你輕鬆增廣見聞提升專業能力!如果你喜歡我們的文章,或是想了解更多特定主題的教學,歡迎到我們的粉絲專頁按讚、留言讓我們知道。你的鼓勵,是我們的原力!

贊助我們的創作

看完這篇文章了嗎? 休息一下,喝杯咖啡吧!

如果你覺得 MyApollo 有讓你獲得實用的資訊,希望能看到更多的技術分享,邀請你贊助我們一杯咖啡,讓我們有更多的動力與精力繼續提供高品質的文章,感謝你的支持!