JSON Schema

    共通部分の切り出し

    definitionsというブロックに指定した値はpropertiesの各設定で使い回すことができます。

    例えば以下は URL の設定を期待するプロパティが2つあるスキーマの例です。(ルートのtitleなどは省略)
    ちなみにpatternは文字列のパターンにマッチしたものだけに絞ることができるプロパティです。

    {
      "type": "object",
      "properties": {
        "link": {
          "type": "string",
          "pattern": "^(http(s)?://)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
        },
        "iconLink": {
          "type": "string",
          "pattern": "^(http(s)?://)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
        },
      }
    }

    ただこのパターンを覚えるのは厳しいので、同じようなプロパティを追加しなければいけなくなった時にコピペして使う他ありません。ただそれも、スキーマの定義部分がぱっと見複雑そうな構造になってしまいます。

    このような場合はdefinitionsプロパティをルートに定義します。

    definitions

    例えばこのようにしてみます。

    {
      "definitions": {
            "pattern": {
                "url": {
                    "type": "string",
                    "pattern": "^(http(s)?://)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
                }
            },
      }
    }

    このdefinitions以下で定義した値は、propertiesの各プロパティでベース(JavaScriptでのObject.assign)のように使うことができます。それには$refというプロパティに#(ルート)からのパスを指定するだけです。子のパス参照は.ではなく/を使います。

    {
      "type": "object",
      "properties": {
        "link": {
          "$ref": "#/definitions/pattern/url"
        },
        "iconLink": {
          "$ref": "#/definitions/pattern/url",
          "description": "`description`設定をこちらだけ追加する"
        },
      }
    }

    これで先ほどよりはスッキリ記述することができました。

    $id を使ってさらに短く

    definitions$idを指定すると#/definitions/path/toと長いパスを置かなくても、$refにその名前を設定するだけで同じ意味になります。

    {
      "definitions": {
            "pattern": {
                "url": {
                    "$id": "#urlPattern",
                    "type": "string",
                    "pattern": "^(http(s)?://)?[\\w.-]+(?:\\.[\\w\\.-]+)+[\\w\\-\\._~:/?#[\\]@!\\$&'\\(\\)\\*\\+,;=.]+$"
                }
            }
        }
    }

    使うと

    {
      "type": "object",
      "properties": {
        "link": {
          "$ref": "#urlPattern"
        },
      }
    }

    別ファイルの definitions を使う

    例えば.jsonファイルが大きくなってきたので同じ階層にdefinitions.jsonというファイルを作りdefinitionsプロパティを分割したとします。その時は#/の前にその読み込みたいファイルまでの相対パスを書いて上げると#/以降のパスは分割先のパスを見るようになります。

    {
      "type": "object",
      "properties": {
        "link": {
          "$ref": "./definitions.json#/definitions/pattern/url"
        },
      }
    }