環境
- ajv 6.12.2
- TypeScript 3.8.3 (on NodeJS)
はじめに
Ajv はブラウザ環境でも使用できますが、ここでは NodeJS(TypeScript)で使った場合の例になります。
githubページ に必要十分な情報はありますが、分量が多いので、ここでは主にスキーマ記述例をまとめています。
ブラウザで使う場合の参照先は、こちら(github)。
Ajv の特徴
-
JSON Schema draft-07 に準拠している。
- 以下のようにして、draft-06 を利用することも可能です(参照先)。
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'))
使い方
import Ajv from 'ajv'
// ここで自分たちの schema ファイルを読み込みます。
import schema from 'somewhere/schema.json'
const ajv = new Ajv()
const validate = ajv.compile(schema)
const valid = validate(data)
if (!valid) console.log(validate.errors)
schema ファイルの例
JSON ではコメントは使えませんが、ここでは説明のために //〜 としてコメントを追加して、且つ改行を入れています。
{
// この値は他のschemaファイルから参照される時に使われるだけなので、
// 実際にこのURLにschemaファイルを置いてダウンロード出来るようにする必要はありません。
"$id": "http://example.com/schemas/schema.json",
// この設定がない場合、draft 6 meta-schema に対してバリデーションが行われます。
"$schema": "http://json-schema.org/draft-07/schema",
"title": "Your title comes here",
"description": "Your description comes here",
// schema ファイルは、基本的に object になると思われるので、
// トップレベルの type は object とします。
"type": "object",
// これにより、定義していないフィールドがあった場合にエラーとします。
// 尚、定義されたレイヤーでしか有効ではありません。
// 階層化された下位層の object に対しては、それ毎に定義が必要です。
// 基本的に、"type": "object" の後にはつけたほうがいいでしょう。
"additionalProperties": false,
// definitions に定義した値は、$ref としてスキーマ内から参照可能です(後述)。
"definitions": {
"languageStrings": {
"description": "This is an example of definition",
"type": "object",
"minProperties": 1,
"examples": [
{
"en": "English title",
"ja": "日本語タイトル"
}
],
}
},
// properties にフィールドの定義をしていきます。
"properties": {
"$schema": {
"type": "string"
},
"stringExample": {
"description": "This is an example of string type",
"type": "string"
},
"stringOfDateFormatExample": {
"description": "This is an example of string type of the date format",
"type": "string"
"format": "date",
"maxLength": 10,
"examples": ["2020-01-23"]
},
"stringOfPatternExample": {
"description": "This is an example of string type of the pattern",
"type": "string",
"pattern": "^0x[!-~]{40}$",
"maxLength": 42
},
"numberExample": {
"description": "This is an example of number type",
"type": "number"
},
"arrayExample": {
"description": "This is an example of array type",
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
},
"enumExample": {
"description": "This is an example of enum",
"enum": [
"one",
"two",
"three"
]
},
"refExample": {
"description": "This is an example of $ref",
"$ref": "#/definitions/languageStrings",
"examples": [
{
"en": "English"
}
]
},
"objectWithAnyOfExample": {
"description": "This is an example of object with anyOf",
"type": "object",
"additionalProperties": false,
"properties": {
"from": {
"type": "string",
"format": "date",
"maxLength": 10,
"examples": ["2020-01-23"]
},
"to": {
"type": "string",
"format": "date",
"maxLength": 10,
"examples": ["2020-03-21"]
}
},
"anyOf": [
{
"required": [
"from",
"to"
]
},
{
"required": [
"from"
]
},
{
"required": [
"to"
]
}
]
},
"dependenciesExample": {
"description": "This is an example of object, dependencies and required",
"type": "object",
// 前述の通り、トップの階層で設定していても、ここでも "additionalProperties": false としなければ、
// 意図しないフィールドが設定できてしまいます。
"additionalProperties": false,
// この定義により、xx を定義した時に、必ず yy を定義する、というルールを付けることが出来ます。
// ここの例では width、height、depth のいずれかが定義された場合は、unit を定義しなければエラーになります。
"dependencies": { "width": ["unit"], "height": ["unit"], "depth": ["unit"] },
// ここに定義されたものは必須項目となります。
"required": [
"note"
],
"properties": {
"width": {
"type": "number"
},
"height": {
"type": "number"
},
"depth": {
"type": "number"
},
"unit": {
"enum": [
"mm",
"cm",
"m"
]
},
"description": {
"$ref": "#/definitions/languageStrings"
},
"note": {
"$ref": "#/definitions/languageStrings"
}
}
},
},
// ここに定義されたものは必須項目となります。
"required": [
"numberExample",
"arrayExample"
],
"minProperties": 0
}
バリデーションルールについて
上記以外にも様々なバリデーションルールが設定可能です。
参照先:
https://ajv.js.org/json-schema.html
https://ajv.js.org/json-type-definition.html
セキュリティ対応
https://github.com/ajv-validator/ajv#security-considerations にリストアップされている内容に準拠しているかを、以下のように Jest などで確認しておきましょう。
import Ajv from 'ajv'
import schema from 'somewhere/schema.json'
// see: https://github.com/ajv-validator/ajv#security-considerations
describe('isSchemaSecure', () => {
const ajv = new Ajv()
const isSchemaSecure = ajv.compile(
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('ajv/lib/refs/json-schema-secure.json')
)
expect(isSchemaSecure(schema)).toBe(true)
})
例えば、以下の通り format
や pattern
を指定した時は、maxLength
を指定しないとチェックに引っかかります。
const isSchemaSecure = ajv.compile(require('ajv/lib/refs/json-schema-secure.json'));
const schema1 = {format: 'email'};
isSchemaSecure(schema1); // false
const schema2 = {format: 'email', maxLength: MAX_LENGTH};
isSchemaSecure(schema2); // true
ブラウザで確認
https://www.jsonschemavalidator.net/ に schema と JSON を入れれば確認できます。
CLI で確認
ajv-cli を使って、CLI でチェックすることも出来ます。