最近遇到的案子需要驗證 API 回傳的 JSON 架構,第一時間當然就是去翻 Postman 的文件。

Postman 裡分別用了 tv4Ajv 這兩個函式做為驗證 JSON 結構,就稍微啃了一下四散各地的文件。

首先找到的是 tv4 的 github repo 上的文件:Tiny Validator (for v4 JSON Schema)

但是因為範例不大夠,不知道怎麼定義 schema 的部份,又去點了最上面的 json-schema draft v4 的連結,得到第二份文件:JSON Schema: A Media Type for Describing JSON Documents

第二份文件裡說關於驗證的部份另外在一份文件,於是得到第三份文件:JSON Schema Validation: A Vocabulary for Structural Validation of JSON

根據第三份文件,可以很簡單堆一些 JSON schema 出來,大概像是這樣:

let schema = {
    type: 'object',
    required: ['sample', 'error', 'message'],
    properties: {
        error: {
            type: 'boolean',
        },
        message: {
            type: 'string',
        },
    },
};

堆好 JSON schema 物件之後,就可以直接丟進 tv4.validate() 用。

由於我需要在不同的 API 都存取這個 JSON schema ,於是就利用 Postman 的環境變數把它存起來:

pm.environment.set('sample-schema', JSON.stringify(schema));

存的時候要記得過 JSON.stringify() ,不然會存成 [Object object] 這種悲劇結果。

如果想要存成比較容易閱讀的 JSON ,就利用 stringify() 的第二個參數達成:

pm.environment.set('sample-schema', JSON.stringify(schema, null, 4));

讀的時候也要記得用 JSON.parse() 處理成物件,不然會是另一場悲劇:

let schemaObj = JSON.parse(pm.environment.get('sample-schema'));

在堆 JSON schema 物件的過程中又翻到一份不錯的文件:Understanding JSON Schema ,這時發現文件已經是 7.0 了,但是用的卻不是 tv7 而是 tv4 ,總覺得哪裡怪怪的,結果在 Postman Sandbox 文件中的 Commonly used libraries and utilities 翻到 tv4 已經被 Postman 的作者加上了 deprecated …好吧,只好換成 Ajv 了。

Ajv 在宣告的時候會需要指定一些選項,我選了 allErrors, jsonPointers 和範例中的 logger

let Ajv = require('Ajv'),
    ajv = new Ajv({
        allErrors: true,
        jsonPointers: true,
        logger: console,
    }),
    sample = 'sample';

然後因為 Ajv 支援 v7 ,所以可以用 const 來指定特定的參數要回傳的值:

let schema = {
    properties: {
        error: {
            const: false,
        },
    },
};

由於我需要檢查的 JSON Object 層級有點深,所以利用了 $ref 來存取:

let schema = {
    definitions: {
        third: {
            type: 'array',
            items: {
                const: 'example',
            },
        },
        second: {
            type: 'array',
            items: {
                type: 'object',
                properties: {
                    third: {
                        $ref: '#/definitions/third',
                    },
                },
            },
        },
    },
    properties: {
        first: {
            $ref: '#/definitions/second',
        },
    },
};

最後在 JSON schema 加上建議的 $schema$id ,測試了一下沒什麼問題。

試的過程中踩的幾個雷有:

  1. JSON 存成全域變數。因為下載環境變數時找不到變數,測試死一片⋯
  2. JSON 讀取時沒用 JSON.parse() ,結果 Ajv 一直回我 no schema with key or ref 然後加上一整串 JSON string ,測試當然又死一片,而且因為錯誤訊息看不出問題在哪,直到一行一行檢查才發現⋯

文章標籤

全站熱搜

repeat :D 發表在 痞客邦 留言(0) 人氣()