拒當前端黑鍋俠!用「jsonschema」來驗證後端回傳的 json 資料結構
這篇文章寫於 2021 年,文中的工具與版本可能已經更新,實作時請以官方文件為準。
本文目錄
開發網頁前端時,會需要用到後端回傳的 api 數據來渲染頁面,如果雙方依照需求規格書好好實作會天下太平;但在現實生活中總是會有例外發生,如果後端傳給前端時的資料格式不夠穩定,前端在渲染的時候就可能會出錯。遇到這種狀況時,「jsonschema」套件就是你的救星!
一、「jsonschema」是什麼?
二、「jsonschema」有哪些優點?
三、「jsonschema」驗證範例
➤ 簡單範例
➤ 複雜點的範例
➤ 常見的陣列範例
四、「jsonschema」其他功能
一、「jsonschema」是什麼?
如果你常常被後端回傳的 json 資料整,那這個套件你一定要學習;他是一個專們用來驗證 json 格式是否符合預期的套件。
可透過下面指令安裝:
npm i jsonschema
二、「jsonschema」有哪些優點?
- 可以詳細定義要驗證的 json 格式,包含內部所有參數的型態(string/number/array/object)
- 驗證結果會用 true/false 回傳
- 發生 error 時,會很明確的指出是在哪個位置出錯
- 可以客製化回傳錯誤的訊息
- 學習及使用非常直覺
三、「jsonschema」驗證範例
簡單範例:
我們要驗證 「4」 這個 instance 的 type 是否為 number。
var Validator = require('jsonschema').Validator;
var v = new Validator();
var instance = 4;
var schema = {"type": "number"};
console.log(v.validate(instance, schema));
原始碼:jsonschema_simple.js(GitHub Gist)
程式執行結果為:
ValidatorResult {
instance: 4,
schema: { type: 'number' },
options: {},
path: [],
propertyPath: 'instance',
errors: [],
throwError: undefined,
throwFirst: undefined,
throwAll: undefined,
disableFormat: false
}
原始碼:jsonschema_simple_result.js(GitHub Gist)
解說:因為 「4」的確是「number」的type,所以在「errors」參數的結果為 empty array。
複雜點的範例:
- 建立「驗證地址格式」的「addressSchema」
- 建立「驗證個人格式」的「schema」,並且讓個人格式的「address」關聯到「addressSchema」
- 建立一個人的物件(p),填入個人訊息
- 使用「jsonschem」提供的「Validator」 function 來驗證物件(p)是否符合個人格式(addressSchema)
var Validator = require('jsonschema').Validator;
var v = new Validator();
// Address, to be embedded on Person
var addressSchema = {
"id": "/SimpleAddress",
"type": "object",
"properties": {
"lines": {
"type": "array",
"items": {"type": "string"}
},
"zip": {"type": "string"},
"city": {"type": "string"},
"country": {"type": "string"}
},
"required": ["country"]
};
// Person
var schema = {
"id": "/SimplePerson",
"type": "object",
"properties": {
"name": {"type": "string"},
"address": {"$ref": "/SimpleAddress"},
"votes": {"type": "integer", "minimum": 1}
}
};
var p = {
"name": "Barack Obama",
"address": {
"lines": [ "1600 Pennsylvania Avenue Northwest" ],
"zip": "DC 20500",
"city": "Washington",
"country": "USA"
},
"votes": "lots"
};
v.addSchema(addressSchema, '/SimpleAddress');
console.log(v.validate(p, schema));
原始碼:jsonschema_complex.js(GitHub Gist)
程式執行結果為:
ValidatorResult {
instance: {
name: 'Barack Obama',
address: {
lines: [Array],
zip: 'DC 20500',
city: 'Washington',
country: 'USA'
},
votes: 'lots'
},
schema: {
id: '/SimplePerson',
type: 'object',
properties: { name: [Object], address: [Object], votes: [Object] }
},
options: {},
path: [],
propertyPath: 'instance',
errors: [
ValidationError {
path: [Array],
property: 'instance.votes',
message: 'is not of a type(s) integer',
schema: [Object],
instance: 'lots',
name: 'type',
argument: [Array],
stack: 'instance.votes is not of a type(s) integer'
}
],
throwError: undefined,
throwFirst: undefined,
throwAll: undefined,
disableFormat: false
}
原始碼:jsonschema_complex_result.js(GitHub Gist)
解說:因為我們在「shemca」這個變數下設定「vote」需要為「integer」的type;但是我們傳入的「vote」內容為「lots」的字串,所以「errors」會回傳一個「is not of a type(s) integer」的錯誤訊息。
常見的陣列範例:
後端 api 其實很常回傳這類陣列的資訊,但因為各種歷史業障;在版本更新時,舊資料在新欄位的資料往往是空的,這時驗證回傳資料的動作就很重要了!
下面是模擬後端回傳「名字」的陣列,用「arraySchema」做格式驗證:
var Validator = require('jsonschema').Validator;
var v = new Validator();
var arraySchema = {
"type": "array",
"items": {
"properties": {
"name": { "type": "string" },
"lastname": { "type": "string" }
},
"required": ["name", "lastname"]
}
}
var arrayName = [
{
"name": "寶寶",
"lastname": "不說"
},
{
"name": "鹿尼",
"lastname": 123
},
{
"name": null,
"lastname": "好想兔"
},
{
"name": "鹿尼"
},
]
console.log(v.validate(arrayName, arraySchema));
原始碼:jsonschema_array.js(GitHub Gist)
程式執行結果為:
ValidatorResult {
instance: [
{ name: '寶寶', lastname: '不說' },
{ name: '鹿尼', lastname: 123 },
{ name: null, lastname: '好想兔' },
{ name: '鹿尼' }
],
schema: { type: 'array', items: { properties: [Object], required: [Array] } },
options: {},
path: [],
propertyPath: 'instance',
errors: [
ValidationError {
path: [Array],
property: 'instance[1].lastname',
message: 'is not of a type(s) string',
schema: [Object],
instance: 123,
name: 'type',
argument: [Array],
stack: 'instance[1].lastname is not of a type(s) string'
},
ValidationError {
path: [Array],
property: 'instance[2].name',
message: 'is not of a type(s) string',
schema: [Object],
instance: null,
name: 'type',
argument: [Array],
stack: 'instance[2].name is not of a type(s) string'
},
ValidationError {
path: [Array],
property: 'instance[3]',
message: 'requires property "lastname"',
schema: [Object],
instance: [Object],
name: 'required',
argument: 'lastname',
stack: 'instance[3] requires property "lastname"'
}
],
throwError: undefined,
throwFirst: undefined,
throwAll: undefined,
disableFormat: false
}
原始碼:jsonschema_array_result.js(GitHub Gist)
解說:除了第一個「寶寶不說」外,我們每個 instance 其實都故意給他錯誤的資訊,來確認這個格式驗證是否生效,錯誤結果在「errors」裡面呈現的很完美。
四、「jsonschema」其他功能
請參考官方網站,上面提供更多詳實的範例。
留言載入中…