開発プロジェクトにおいて、設定ファイルの妥当性を担保するために最適なバリデーションツールを検討した。
比較対象
本比較では、以下の3つのCLIツールを対象とした。
| ツール名 | 特徴 | リポジトリ |
|---|---|---|
| ajv-cli | Node.jsエコシステムで最も有名な「Ajv」のCLI版。 | ajv-validator/ajv-cli |
| schemalint | giantswarm氏作成。見た時点でGitHubのスター数は13と少ないが、未だにコミットがあってメンテされているようだった。 | giantswarm/schemalint |
| check-jsonschema | Python製。結論から言うとこれしか選択肢がない。 | python-jsonschema/check-jsonschema |
検討はしたものの比較から除外したツール
- jsonschema-lint (jacksmith15/jsonschema-lint): 長期間更新が停止しているため。
- TypeSpec (microsoft/typespec): データモデリング言語としての側面が強く、スキーマから検証しないため。
- json-schema-org/json-schema-linting (json-schema-org/json-schema-linting): 実装が未完了。
比較方法
今回の検証では、よく使う devbox のスキーマを使用する。
できればJSONスキーマファイルを用意せずとも$schemaプロパティを自動で参照してくれたらよかったが、schemalint以外はどのツールもやってくれなかった。
よって事前にスキーマ定義ファイルをダウンロードし、ローカルにdevbox.schema.jsonとして保存した上で検証を行う。
また、テストデータには正当なJSON (valid.json)と、不正なプロパティを含むJSON (invalid.json)を使う。もちろん、両方ともJSONとしては正しく、スキーマに沿っているかどうかの違いのみ。
{
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.17.1/.schema/devbox.schema.json",
"packages": [],
"shell": {
"init_hook": [
"echo 'Welcome to devbox!' > /dev/null"
],
"scripts": {
"test": [
"echo \"Error: no test specified\" && exit 1"
]
}
}
}
{
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.17.1/.schema/devbox.schema.json",
"packages": [],
"foo": "bar",
"shell": {
"init_hook": [
"echo 'Welcome to devbox!' > /dev/null"
],
"scripts": {
"test": [
"echo \"Error: no test specified\" && exit 1"
]
}
}
}
また、それぞれの比較には以下のコマンドを使った。
ajv-cli
ajv validate -s devbox.schema.json -d valid.json
ajv validate -s devbox.schema.json -d invalid.json
schemalint
schemalint verify valid.json
schemalint verify invalid.json
check-jsonschema
check-jsonschema --schemafile devbox.schema.json valid.json
check-jsonschema --schemafile devbox.schema.json invalid.json
比較結果
ajv-cli: スキーマを読み込めない
$ ajv validate -s devbox.schema.json -d valid.json
schema devbox.schema.json is invalid
error: no schema with key or ref "http://json-schema.org/draft-04/schema#"
error: "ajv" exited with code 1
$ ajv validate -s devbox.schema.json -d invalid.json
schema devbox.schema.json is invalid
error: no schema with key or ref "http://json-schema.org/draft-04/schema#"
error: "ajv" exited with code 1
AjvはDraft-04形式のスキーマを読み込もうとするとエラーになる。
AjvにはAjv独自のスキーマを描く必要がある。
そもそも、更新が5年前で止まっているのはどうかと。
schemalint: そもそも実装されてないかも
$ schemalint verify valid.json
Errors (1)
Schema is not normalized. Run 'schemalint normalize valid.json -o valid.json --force'.
---
Verification result
[SUCCESS] Input is valid JSON Schema.
[ERROR] Input is not normalized.
$ schemalint verify invalid.json
Errors (1)
Schema is not normalized. Run 'schemalint normalize invalid.json -o invalid.json --force'.
---
Verification result
[SUCCESS] Input is valid JSON Schema.
[ERROR] Input is not normalized.
検証した結果、schemalintはスキーマに沿っているかどうかを見てないことがわかる。
リポジトリをよく見たらテストケースが存在せず、どう使うのかもわからないままです。よくメンテされていないと判断。
check-jsonschema: 実用的で最も正確なエラー表示
$ check-jsonschema --schemafile devbox.schema.json valid.json
ok -- validation done
$ check-jsonschema --schemafile devbox.schema.json invalid.json
Schema validation errors were encountered.
invalid.json::$: Additional properties are not allowed ('foo' was unexpected)
非常に優秀。正当なデータはパスし、不正なデータ(invalid.json)については、追加したfooプロパティが許可されていないことを明確に指摘。これが最も信頼できる選択肢。
今回の比較結果をまとめると以下の通り。
| 評価項目 | ajv-cli | schemalint | check-jsonschema |
|---|---|---|---|
| バリデーション成否 | × (エラー停止) | × (データ未検証) | ○ (正確に検証) |
| 偽陽性の発生 | あり (Draftバージョンの不一致) | なし | なし |
| 偽陰性の発生 | なし | あり (中身を無視する) | なし |
| エラーメッセージ | 難解 (内部エラー) | 紛らわしい (成功と表示) | 明快 (行数・原因を特定) |
まとめ
今回の比較から、check-jsonschema が唯一信頼できるツールであることが証明された。
開発プロジェクトに組み込むのであれば、迷わず check-jsonschema を採用すべきだ。GitHub ActionsなどのCI環境でも導入が容易であり、バリデーションツールとしての完成度が頭一つ抜けている。