白猫のメモ帳

C#とかJavaとかJavaScriptとかHTMLとか機械学習とか。

スキーマファイルで設定ファイルを管理しやすくする(JSON Schema / XML Schema)

こんばんは。
気がつけばいろいろな果物が並んでいて秋を感じます。

さて、package.jsonなどの設定ファイルをVS Codeなどで編集していると補完が効いたり、エラーチェックをしてくれたりと便利です。
JSONでこの仕組みを提供しているのがJSON Schemaという機能で、これは設定ファイルを作ることができます。
今回はこれを反映してみます。あとついでにXML Schemaも。

github.com

ちなみにこの記事はJSON Schemaの文法を説明するような内容ではないのでご注意ください。

どうやって設定するの

よく知られているJSONファイルなどは自動的にJSON Schemaが反映されます。
これはJSON Schema Storeというところに登録されているものです。
www.schemastore.org

自分で設定するにはファイル自体に明示的に指定する方法と、VS Codeなどのエディタ側に設定を書く方法があります。
それぞれの設定ファイルでどういう設定をすればいいかを確認してみます。

JSON

Json Schemaを使ってスキーマを定義します。Json Schema自体もJSONファイルで、名前は「~.schema.json」とすることが一般的なようです。例えばこんな感じ。

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Example Schema",
  "description": "サンプルのスキーマ情報です",
  "type": "object",
  "properties": {
    "type": {
      "type": "string",
      "enum": [ "food", "drink" ],
      "description": "商品種別"
    },
    "name": {
      "type": "string",
      "description": "商品名"
    },
    "price": {
      "type": "integer",
      "description": "金額"
    }
  },
  "required": [ "type", "name", "price" ],
  "additionalProperties": false
}

ファイル内で指定するときには「$schema」で指定します。
パスで指定していますが、http(s)でも大丈夫です。

{
  "$schema": "../../schema/sample.schema.json",
  "products": [
    {
      "type": "food",
      "name": "apple",
      "price": 100
    },
    {
      "type": "drink",
      "name": "orange juice",
      "price": 200
    }
  ]
}

VS Codeで一括で指定する場合、「.vscode/settings.json」に「json.schemas」を指定します。

{
    "json.schemas": [
        {
            "fileMatch": [
                "/data/from_setting_file/**/*.json"
            ],
            "url": "./schema/sample.schema.json"
        }
    ]
}

YAML

YAMLファイルにもJSON Schemaを適用することができます。
ファイル内で指定するときには「# yaml-language-server: $schema=~」で指定します。

# yaml-language-server: $schema=../../schema/sample.schema.json

products:
  - type: food
    name: "apple"
    price: 100
  - type: drink
    name: "orange juice"
    price: 200

VS Codeで一括で指定する場合、「.vscode/settings.json」に「yaml.schemas」を指定します。「json.schemas」と文法が違うのでお間違えなく。
VS拡張「YAML Language Support by Red Hat」をインストールする必要があります。

{
    "yaml.schemas": {
        "./schema/sample.schema.json": [
          "/data/from_setting_file/**/*.yaml"
        ],
    }
}

XML

XMLファイルはXML Schemaを設定することができます。名前は「~.schema.xsd」とすることが一般的なようです。手で書くのはちょっとつらそうなのでXMLから生成がおすすめ。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="main">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="sub1" type="xs:string"/>
                            <xs:element name="sub2" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

ファイル内で指定するときには「xsi:noNamespaceSchemaLocation="~"」で指定します。「xmlns:xsi=~」も必要です。

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="../../schema/sample.schema.xsd">
    <main>
      <sub1>value1</sub1>
      <sub2>value2</sub2>
    </main>
</root>

VS Codeで一括で指定する場合、「.vscode/settings.json」に「xml.fileAssociations」を指定します。
VS拡張「XML Language Support by Red Hat」をインストールする必要があります。

{
    "xml.fileAssociations": [
        {
            "pattern": "**/from_setting_file/*.xml",
            "systemId": "schema/sample.schema.xsd"
        }
    ]
}

パスの指定時に先頭を「**/~」ではなく「/hoge/~」のように固定のパスにすると何故か指定が効きません。
issueが上がっているようなのでバグなんですかね?

スキーマ作るのが大変なんだけどね

個人的にちょっと設定ファイル作るくらいだと割に合わないですが、複数人で使ったり、長期にわたってメンテナンスするものだと作っておくと便利そうですよね。
ミスが少なくなるのもそうですが、開発体験を良くするためにもこういったちょっとした親切を積極的に取り入れたいものです。