Load Complex Json Schema With Python
最近拿 JSON schema 來驗證自己的 API 回傳內容有沒有錯誤,在過程中遇到一點小障礙─無法讀取複雜的 JSON schema。
假設有支 API /v1/products/{product_id}
,它的 schema 如下:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product resource",
"description": "A product resource",
"type": "object",
"additionalProperties": false,
"properties": {
"data": {
"type": "object",
"additionalProperties": false,
"properties": {
"product": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"price": {
"type": "integer"
},
"created_at": {
"type": "integer"
},
"updated_at": {
"type": "integer"
}
},
"required": [
"id",
"name",
"price",
"created_at",
"updated_at"
]
}
}
}
},
"required": [
"data"
]
}
這種簡單的 schema,直接用 json
讀取是沒問題的
import json
with open('specs/product-schema.json', 'r') as schema:
product_schema = json.loads(schema.read())
但總會有一些意料之外的事
如果今天有些 schema 會一直出現,你不想每個地方都重複寫一樣的東西,那你可能會需要 reference
,而 File Reference 就是其中一種,像是:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product resource",
"description": "A product resource",
"type": "object",
"additionalProperties": false,
"properties": {
"data": {
"type": "object",
"additionalProperties": false,
"properties": {
"product": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"price": {
"type": "integer"
},
"created_at": {
"$ref": "unix-timestamp.json"
},
"updated_at": {
"$ref": "unix-timestamp.json"
}
},
"required": [
"id",
"name",
"price",
"created_at",
"updated_at"
]
}
}
}
},
"required": [
"data"
]
}
created_at
和 updated_at
原本是 integer
,但現在會 refer to unix-timestamp.json
這就無法直接用 json
完整的解析出來了,你可以自己寫一個 RefResolver
,或是直接用 jsonref,懶人如我當然就是後者啦 XD
from os.path import json, dirname
import jsonref
base_uri = f'file:{join(dirname(__file__), "specs/")}'
with open('specs/product-schema.json', 'r') as schema:
product_schema = jsonref.loads(
schema.read(), base_uri=base_uri, jsonschema=True)
如此一來便能把整個 json 展開來,搭配 jsonschema 做 api validation