VS Code で Json Schema を作って使う


🥞はじめに

ちょっとしたデータを集めて JSONYAML 形式で保存したいときがある。
このデータ収集が中長期的におよぶ場合、「どの項目を保存することにしたんだっけ……?」ってなるのを防ぎたい。

よって、Json Schema を作成することで JSON データのスキーマを定義する。
VS Code では Json Schema を指定することでインテリセンスが有効になり、JSON データの入力も楽になって嬉しい。

やること
  1. Json Schema を作成

  2. Json Schema のドキュメント( in OpenAPI )を作成

  3. 作成した Json Schema に則った JSON データを作成

Table 1. 環境
App Version

VS Code

1.63.2

Json Schema

Draft 7

Json Schema(OpenAPI)プレビュー用

OpenAPI (Swagger) Editor

4.8.1

Live Preview

0.2.12

⚙️Json Schema 作成

  1. .json ファイルを新規作成。[1]

  2. VS Code が対応している Json Schema の仕様バージョン Draft 7 を指定(参考)。

    { "$schema": "http://json-schema.org/draft-07/schema#" }
  3. 上記より、Json Schema のインテリセンスが有効化されるので、それを利用してゴリゴリ書いていく。
    Json Schema についての詳細は Understanding JSON Schema ドキュメントを参考にする。

Example 1. Json Schema サンプル
myschema.json
{
  "$schema": "http://json-schema.org/draft-07/schema#",   (1)
  "title": "Fleet",
  "description": "Fleet collection",
  "type": "object",
  "required": ["basic", "spec"],  (2)
  "properties": {
    "basic": { "$ref": "#/definitions/BasicInfo" },   (3)
    "spec": { "$ref": "#/definitions/Spec" }          (3)
  },
  "definitions": {    (4)
    "BasicInfo": {
      "description": "基本情報",
      "type": "object",
      "required": ["registry", "name", "class", "type"],  (2)
      "properties": {
        "registry": { "type": "string", "minLength": 1 },
        "name": { "type": "string", "minLength": 1 },
        "class": { "type": "string", "minLength": 1 },
        "series_number": { "type": "integer", "minimum": 1 },
        "type": {
          "type": "string",
          "enum": [   (5)
            "戦艦",
            "巡洋戦艦",
            "航空母艦",
            "護衛空母",
            "重巡洋艦",
            "軽巡洋艦",
            "駆逐艦",
            "潜水艦",
            "海防艦",
            "補助艦艇"
          ]
        },
        "launched": { "type": "string", "format": "date" }
      },
      "examples": [   (6)
        {
          "registry": "JPN",
          "name": "赤城",
          "class": "赤城型",
          "series_number": 1,
          "type": "航空母艦",
          "launched": "1925-04-22"
        }
      ]
    },
    "Spec": {
      "type": "object",
      "required": ["displacement", "length", "speed"],  (2)
      "properties": {
        "displacement": {
          "description": "基準排水量(ton)",
          "type": "integer",
          "minimum": 1
        },
        "length": {
          "description": "全長(m)",
          "type": "number",
          "minimum": 0.01
        },
        "power": {
          "description": "エンジンパワー(hp)",
          "type": "integer",
          "minimum": 1
        },
        "speed": {
          "description": "最大速力(kt)",
          "type": "number",
          "minimum": 1.0
        }
      },
      "examples": [   (6)
        {
          "displacement": 36500,
          "length": 260.67,
          "power": 133000,
          "speed": 31.2
        }
      ]
    }
  }
}
1 Json Schema の宣言
2 object における必須プロパティを指定。
3 $ref キーワードにより他のスキーマを参照している。
Json Schema 評価時に参照されているスキーマが取得され、ここに適用される。
4 $ref で参照するスキーマをここで定義する。
5 値として許可するものを列挙し、この中から選択させるようにする。
6 このスキーマがとりうる値の例を記述。
上記 Json Schema を適用したJSONデータの例
{
  "$schema": "./myschema.json",
  "basic": {
    "registry": "USA",
    "name": "ジョンストン",
    "class": "フレッチャー級",
    "series_number": 119,
    "type": "駆逐艦",
    "launched": "1943-03-25"
  },
  "spec": {
    "displacement": 2700,
    "length": 114.76,
    "power": 60000,
    "speed": 35.0
  }
}

Json Schema 書き方 Tips

Json Schema を書く上でのちょっとしたメモ。

Json Schema の宣言

$schema キーワードで Json Schema およびそのバージョンを宣言する。
JSONデータのルートで定義する必要がある。

Example 2. バージョン Draft 7 を宣言
{ "$schema": "http://json-schema.org/draft-07/schema#" }

$ref キーワードによる他スキーマ参照

$ref キーワードを使って他のスキーマを参照することができる。
これにより、同じ設定を流用できたり深いネストになってしまうことを避けられる。

$ref の値は Base URI からの URI 参照となる。
ファイル内部のスキーマを参照する場合、ルートは # で表現され、プロパティごとに / で区切る。

Example 3. $ref
{
  "type": "object",
  "properties": {
    "color": { "$ref": "#/definitions/SelectColor" },
  },
  "definitions": {    (1)
    "SelectColor": {
      "type": "string",
      "enum": ["red", "blue", "yellow"]
    }
  }
}
1 参照用のスキーマは definitions キーワードで定義する[2]

プルダウンリスト(ドロップダウンリスト)的な使い方をしたい

複数の固定値の中から1つを選択させたい場合は、enum キーワードを利用する。

Example 4. 値を固定値から選ばせる
{ "enum": ["yellow", "green", "blue"] }
正規表現で string 値を制限したい場合は pattern キーワードを利用する。

任意のキーを許可したい

additionalProperties キーワードを利用すればいい。

Example 5. 任意のキーを許可
schema.json
{
  "type": "object",
  "additionalProperties": { "type": "string" }  (1)
}
1 任意キーの値について、スキーマを与える。
スキーマではなく true を与えると任意の値をとる。
{ "example": "ok" }
一定の文字列パターンに従ったキーを許可したい場合は patternProperties を利用する。

default, examples, example の違いについて

default

デフォルト値を明示するために使われる。
あくまでデフォルト値を明示するだけであり、ここで指定したからといって欠損値を埋める機能はない[3]

examples

スキーマに従ったJSONデータ値の例。
利用者に向けた使い方の例示。

example

Open API で参照されるJSONデータ値の例。
Open API v3.0.x では examples キーが参照されないため、代わりにこちらを使う。

スキーマの合成

allOf

すべてのサブスキーマに対して一致する必要がある(AND)。

anyOf

サブスキーマの内いずれかに一致する必要がある(OR)。

oneOf

サブスキーマの内ただ1つに一致する必要がある(XOR)。

not

与えられたスキーマに一致してはならない(NOT)。

条件分岐

  • 依存するプロパティやスキーマを指定する dependentRequired, dependentSchemas キーワード

  • If-Then-Else 構文の if, then, else キーワード

が使える。

📚OpenAPIJson Schema ドキュメント代わりに利用する

Json Schema をドキュメント化するツールはいくつかあるが、それぞれ ruby だったり node.js だったりの環境構築する必要があるので面倒くさい。

なので今回は RESTful API のドキュメントとして広く使われる OpenAPI ドキュメントを作成し、その中の一部として Json Schema を取り込ませる方法をとる。
OpenAPI エディター兼ビューワーとしては、VS Code の拡張機能 OpenAPI (Swagger) Editor を使用した。

Example 6. OpenAPI で Json Schema ファイルを参照
OpenAPI ドキュメントの作成手順
  1. VS Code 拡張機能 OpenAPI (Swagger) Editor をインストール。

  2. コマンドパレットから Create new openapi v3.0 file をクリック。
    JSON または YAML 形式で新規作成される。

  3. content 以下を追記し、作成した Json Schema を参照させる。

  4. あとは Shift + Alt + P ショートカットキーで OpenAPI プレビューが描画される。

api.yml
openapi: "3.0.2"
info:
  title: API Title
  version: "1.0"
servers:
  - url: https://api.server.test/v1
paths:
  /test:
    get:
      responses:
        "200":
          description: OK
          content:  (1)
            application/json:
              schema:
                $ref: "myschema.json"   (2)
1 この content 以下を追加。
2 Json Schema ファイルを指定する。
上記のプレビュー例
api.yml のプレビュー例
OpenAPI プレビュー表示

OpenAPI (Swagger) Editor のプレビュー描画エンジンを redoc に変更しておいたほうがスキーマを確認しやすい。

settings.json
{
  "openapi.defaultPreviewRenderer": "redoc"
}

📈Json Schema を有効化して JSON データを作成

VS Code 上で利用することを前提。

VS Code でインテリセンスを有効化するには、

  1. 🌟 JSON ファイルにて $schema キーワードの値に Json Schema ファイルを指定する。

  2. settings.json で適用する Json Schema とファイルパターンを指定する。

の2通り。

あとは有効化されたインテリセンスをばんばん使って JSON を書けばいい。

Example 7. VS Code で特定の Json Schema を有効化する設定
data.json
{
  "$schema": "./myschema/schema.json",
  ...
}

または

.vscode/settings.json
{
  "json.schemas": [
    {
      "fileMatch": ["/*.my.json"],      (1)
      "url": "./myschema/schema.json"   (2)
    }
  ]
}
1 スキーマを適用するファイルパスのパターンを指定。
ワイルドカード(*)や否定演算子(!)も利用できる。
2 使用する Json SchemaURI を指定。
ローカルファイルを相対参照する場合、カレントディレクトリ(.)を指定しないとうまく解釈してくれない。

😫補足: Json Schema 書くのしんどい

すでに JSON データがある場合は quicktype を使うと楽ができる。
quicktypeJSON データから Json Schema を生成[4]してくれるツール。

quicktypeオンラインツールとしても提供されており、簡単に試せる。

1. YAML ファイルでスキーマを作成し、yq ツールを使って .json ファイルに変換する、という方法もある。
2. Draft 2019-09 以降は $def キーワードに変更されたらしい。
3. Json Schema はJSONデータの仕様を定めるだけなので当然。欠損値を埋める処理は、JSONデータを受け取ったシステム側で実装されるべき。
4. 他に TypeScriptGo 言語のコードへの変換も可能。