logo
menu
post-banner

2024.3.26

SHARE ON |

fb
fb
fb

Why JSON Schema

在撰寫自動化測試時,遇到 get 的 API,因為回傳的資料非常大一包,若將每個 property 拆開單獨寫一個 test 會導致 test 過多,但若包在一起用傳統寫法又缺乏準確報錯,因此尋找一個 solution 來驗證 JSON 回傳的格式是否正確,若錯誤也會針對錯誤欄位 assert error

Overview

這個工具是以 JSON 格式來定義要驗證的 JSON 資料,讓使用者透過這個工具簡單設計出自訂格式的 JSON parser,可以用在 testing 或 backend 輸入輸出格式的定義,還有酷炫的功能可以按照格式生產隨機的測試資料。

語言支援非常多,只要用 JSON 格式定義好物件後他的 validator 支援 C#, C++, python, java, JS...等,種類繁多,其中這次會用 JS 套件 Ajv JSON schema validator,該套件也有內建在 postman 裡,語法如下


pm.response.to.have.jsonSchema({JSON schema})

Basic schema


{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"properties": {
"productId": {
"description": "The unique identifier for a product",
"type": "integer"
},
"warehouseLocation": {
"description": "Coordinates of the warehouse where the product is located.",
"$ref": "https://example.com/geographical-location.schema.json"
}
},
"required": [ "productId" ]
}

這是一個簡單的範例,他定義了一個 product 的 JSON schema

Schema Keyword

$符號開頭,用來定義 schema 的特殊屬性,若只是單純要驗證資料沒有特殊的外部需求,完全不寫也沒關系

$schema ****代表你寫的 JSON Schema 文件遵循的規範是哪一個版本,在上面這個範例中他的版本是 draft/2020-12 這個版本

$id是這個 schema 的 unique 識別號,只要用在外部使用$ref 時可以透過它識別出要 reference 誰

$ref可以透過它來 reference 一些公開的 schema,或是分檔撰寫 schema 再 reference 在一起,在上面這個範例是 warehouseLocation 這個 property 必須依照"https://example.com/geographical-location.schema.json"的schema格式

Schema annotation

titledescription屬於此類,主要用於紀錄人類可讀的說明性資訊

Validation keyword

各類功能不同的 validation keyword,用來規範 schema 必須依循的規則,在上面的範例中propertiestyperequired都屬於這類

properties 規範了這個 schema 裡會出現的 properties,再針對各自的 property 可以有更細的規範

type 最簡單的 validation keyword,用來規範資料的 data type,常見的有 string、integer、number(包含 int、float)

required 搭配 properties 使用,用來規範一定要出現的 property

Nested structure

JSON 最常見的就是 object 裡包 object 或包 array,當然它也可以規範出 nested 的 schema


{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"properties": {
"productId": {
"description": "The unique identifier for a product",
"type": "integer"
"tags": {
"description": "Tags for the product",
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"dimensions": {
"type": "object",
"properties": {
"length": {
"type": "number"
},
"width": {
"type": "number"
}
},
"required": [ "length", "width", "height" ]
}
},
"required": [ "productId"]
}

array 可以用items來規範內部物件的格式,object 則是用properties

還有其他的 validation keywords 可以參考 reference 裡的 understanding JSON schema 連結

examples

一些常見的應用和這次撰寫測試裡用到的實際案例


"personality": {
"type": "array",
"minItems": 5,
"maxItems": 5,
"items": {
"type": "number",
"minimum":0,
"maximum":1
}
}

性格是固定長度為 5 的 float array,每個 flaot 的最小值為 0 最大值為 1


"animalName":{
"type":["string","null"]
},

animalName 會是 string,但若在未選擇寵物前回傳 null 是正常行為


{
"title": "ID card number",
"type": "string",
"pattern": "^[A-Z]{1}[0-9]{9}$"
}

依照 regular expression 來驗證符合身分證字號格式的字串


{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"properties": {
"productId": {
"description": "The unique identifier for a product",
"type": "integer"
"tags": {
"description": "Tags for the product",
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"additionalProperties":false
}

additionalProperties 不允許出現properties 以外的其他 property,也可以直接規範其他額外 property 或單純設為 true(預設就是 true)


"additionalProperties":{ "type":"string" }
"additionalProperties":true

test your test

一個遇到 error 卻不會噴 error 的 test 是沒有意義的,務必在寫完 JSON schema 後先自己玩弄一下看看有沒有設計瑕疵

JSON Schema Validator - Newtonsoft

Reference

Getting Started Step-By-Step

驗證資料的好幫手 - JSON Schema Validator · Issue #2 · Hsueh-Jen/blog

Understanding JSON Schema - Understanding JSON Schema 2020-12 documentation

AINIMAL人工社群智慧養成

找到與你最契合的人