【分享】jsonschema 應用於 RESTful API 開發

JSON Schema 可以定義一套規則來驗證 JSON 格式,目前是 draft v4,個人覺得在 RESTful API 開發上非常方便,除了不需要再寫噁心的欄位判斷以外(有時候欄位判斷邏輯甚至會很複雜),定義好的 schema 也可以直接拿來用在 document 上再做點修改。

以下是以 node.js + koa + jsonschema 的例子,使用的是 jsonschema 這套 validator 實作

先來寫一個簡易的 koa middleware

var Validator = require('jsonschema').Validator;
var v = new Validator();

module.exports = function schema(schemaObj) {
  return function *(next) {
    // 當 query 出現 schema-help 時, 回應 schemaObj 給 client 參考

    if (this.request.query.schema-help !== undefined) {
      this.body = schemaObj;
      return;
    }
  
    var result = v.validate(this.request.body, schemaObj);
    // 當 schema 不匹配時, 會產生錯誤訊息在 result.errors

    if (result.errors.length) {
      console.log('schema-errors:', result.errors);
      this.body = {
        message: 'schema not match',
        errors: result.errors
      };
      return;
    }
    yield next;
  };
}

然後 route 就可以像這樣寫

var Koa = require('koa');
var body = require('koa-body');
var Router = require('koa-router');
var schema = require('./middlewares/schema');

var app = new Koa();
var router = new Router();

// 新增文章

router.post('/article', schema({
  type: 'object',
  properties: {
    title: { type: 'string', maxLength: 100 },
    content: { type: 'string' },
    tags: {
      type: 'array',
      items: { type: 'string', maxLength: 20 }
    },
    public: { type: 'boolean' }
  },
  required: [ 'title', 'content', 'tags' ],
  additionalProperties: false
}), function *() {
  // API logic... 

});

app.use(body());
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);

這個是簡易的新增文章例子,有時候我們甚至需要做更複雜的欄位判斷,試想不用 validator 做這些驗證會花多少精神...

最完整的 jsonschema 用法可以參考 official document。(比較重要的部分在第五個章節)

例舉幾個自己常用的

  1. min*, max*: number, string, array, object 的限制 (5.1 ~ 5.4)
  2. pattern, enum: regex 和 enum
  3. required: 在 object properties 中的必填欄位
  4. additionalProperties: 表示在 object properties 中是否允許增加未知欄位, 預設為 true
  5. dependencies: 可以在欄位間建立相依關係,例如讓兩個非必填欄位如果有填的話必須兩個都存在,像是 latitude, longitude
  6. anyOf, allOf, oneOf, not: 參考這裡會更清楚

draft v5

v5-Proposals

jsonschema + is.js ?

is.js 是一個很棒的 check library,提供了不少方法在一般情況下不需要再寫 regex 做判斷,於是我把它帶到 jsonschema 來用,可以參考這個套件: jsonschema-is-js-plugin

目前主要是針對這套 validator 實作,也是例子中所使用的。

comments powered by Disqus