JSON SchemaでJSONのValidationをする
JSONのValidationをしたい
JSONがデータのフォーマットとして使われだして久しいですが、
現在ではREST APIのやり取り、ElasticsearchやMongoDBでの通信、設定ファイルなど
さまざまな場所で使用されています。
データ形式がシンプルで、柔軟性があるのがJSONの特徴ですが、
データの定義をしっかり決めたいときもあります。
JSONのValidationをする必要があり、
JSON SchemaやJSONのValidationを使用したのでその紹介をします。
quickType
ここでも紹介されていますが、quicktypeとは
JSON Schemaからいろいろな言語コード(Swift, Go, Rust,JavaScript等)を生成したり、
JSONデータからJSON Schemaを生成したりできるツールです。
JSON SchemaはJSONを記述したり検証したりするための設計書のようなもので、
どんなフィールドがあるとか、そのフィールドが必須なのか等がわかります。
//quicktypeで生成したJSON Schema { "$schema": "http://json-schema.org/draft-06/schema#", "$ref": "#/definitions/Schema", "definitions": { "Schema": { "type": "object", "additionalProperties": false, "properties": { "foo": { "type": "string" } }, "required": [ "foo" ], "title": "Schema" } } }
quicktypeをcliで使う
npmを使えばインストールできます。
Globalオプションでインストールしましょう。
% npm install -g quicktype
では、JSON SchemaをJSONから生成してみます。JSONデータをもとにschema.jsonが生成されます。
% echo '{"foo" : "bar"}' | quicktype -o schema.json --lang schema % cat schema.json { "$schema": "http://json-schema.org/draft-06/schema#", "$ref": "#/definitions/Schema", "definitions": { "Schema": { "type": "object", "additionalProperties": false, "properties": { "foo": { "type": "string" } }, "required": [ "foo" ], "title": "Schema" } } }
これはコマンドラインから実行する方法ですが、今回はJavaScriptのコードから
quicktypeを実行してJSON Schemaを生成してみましょう。
環境
今回使用した動作環境は以下のとおりです。
- OS : MacOS X 10.14.5
- node.js : v12.9.0
quicktype-core
コード内でJSON Schemaを生成方法について調べたところ、quicktype-coreを使えば
コード内でSchemaの生成などができるようになるとのことです。
npmをつかってインストールしましょう。
% npm install quicktype-core
quicktype-coreライブラリを使って任意のJSON文字列からJSON Schemaを生成してみます。
//sample.js const {InputData, JSONSchemaTargetLanguage, jsonInputForTargetLanguage, quicktypeMultiFileSync} = require("quicktype-core"); //JSON Schema生成元モデル const json = "{\"foo\" : 10,\"bar\": \"abc\"}"; const input = new InputData(); const srcJsonData = {name: 'SampleSchema', samples: } const makeInput = () => jsonInputForTargetLanguage(new JSONSchemaTargetLanguage(), undefined, false) input.addSourceSync("json", srcJsonData, makeInput) const qtResult = quicktypeMultiFileSync({ lang: new JSONSchemaTargetLanguage(), inputData: input }); //生成したスキーマ const schema = JSON.parse(qtResult.get("stdout").lines.join('')); console.log(schema);
sample.jsを実行してみると、JSON Schemaが取得できるようになりました。
% node sample.js { '$schema': 'http://json-schema.org/draft-06/schema#', '$ref': '#/definitions/SampleSchema', definitions: { SampleSchema: { type: 'object', additionalProperties: false, properties: [Object], required: [Array], title: 'SampleSchema' } } }
ajvつかってvalidation
JSON Schemaを取得できたら、対象のJSONがそのSchemaに対してvalidかどうかチェックします。
ajvというJSON Schema Validatorを使ってチェックしましょう。
% npm install ajv
さきほどのプログラムに、ajvを使ったvalidationを追加します。
・・・ const Ajv = require('ajv'); const ajv = new Ajv({allErrors: true}); ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json')); const testValidJson = {"foo": 40,"bar":"def"}; var valid = ajv.validate(schema, testValidJson); console.log(valid);
testValidJsonはJSON Schema的にvalidなので問題ありません。
では、↓のようにJSON SchemaにあっていないJSONにしてみましょう。
・・・ const Ajv = require('ajv'); const ajv = new Ajv({allErrors: true}); ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json')); const testInvalidJson = {"foo": "aaa","buzz":[]}; valid = ajv.validate(schema, testInvalidJson); if (!valid) console.log(ajv.errors);
JSON Schemaと合致していないので、エラーが表示されます。
% node sample.js [ { keyword: 'additionalProperties', dataPath: '', schemaPath: '#/definitions/SampleSchema/additionalProperties', params: { additionalProperty: 'buzz' }, message: 'should NOT have additional properties' }, { keyword: 'type', dataPath: '.foo', schemaPath: '#/definitions/SampleSchema/properties/foo/type', params: { type: 'integer' }, message: 'should be integer' }, { keyword: 'required', dataPath: '', schemaPath: '#/definitions/SampleSchema/required', params: { missingProperty: 'bar' }, message: "should have required property 'bar'" } ]
型違いやフィールド有無についてエラーが表示されています。
※設定によりエラーにするかどうかの変更も可能
これでJSONのValidationチェックができるようになりました。