JSON Schemaの意味や書き方を理解してバリテーションをかけよう!

みなさんこんにちは!今日はJSON Schemaについて話していこうと思います!

目次

JSON Schemaとは何か?

みなさん、そもそもJSON Schemaが何か、どういうものかということは知っていますか?JSON Schemaとは名前の通りJSON形式で書かれたSchemaのことです。

Schemaとはデータベースを扱うときによく出てくる単語ですが、簡単に言えば文書をある構造の元、定義したもののことです。Railsであれば、schema.rbに決まった構造でDBの内容を書いてあげれば読み込むことでDBを再現できます。

JSON SchemaにはJSON Hyper-SchemaとJSON Schema2つ種類があるので次項で紹介していきます。また、公式ドキュメントはこちらです。

JSON Schemaの特徴

公式ページをみてみると、JSON Schemaの特徴は、

  • 既存のデータを読み取ってくれる
  • 全てJSONで記述
  • 人間と機械が読みやすい
  • 送信するデータや、自動テストでのバリテーションが便利

とありますね。タイトルにもありますが、バリテーションとは入力内容にミスが無いかどうかチェックする行為のことを指します。

JSON Hyper-Schemaの特徴

JSON Hyper-Schemaと特徴は、

  • インスタンスデータとURI Templatesが共用できる
  • JSONスキーマからクライアントデータが記述できる

などですね。ここらへんについては詳しく理解する必要はありませんが、JSON Schemaを使うときは使うことによってどのようなメリットがあるのかを考えるようにしましょう。

JSON Schemaのメリット・デメリット

ここで、JSON Schemaのメリットとデメリットをまとめてみます。まずメリットですが、

  • バリテーションをかけることができる
  • テストを自動化できる
  • テスト用のサーバとして使える
  • APIドキュメントを作成できる

デメリットは、

  • JSONを書くのがだるい

といったところでしょうか。JSONをそのまま書くのは、ミスにつながり消耗するので、ymlで書いたものを変換するという方法が一般的です。

メリットは色々ありますが、全ては紹介しきれないので今日はまず最初に思いつくであろうバリテーションをかけるといったことを実際に行ってみましょう!

JSON Schemaを用意しよう!

まずは、JSON Schemaを用意していきましょう。テスト用にJSONデータは、こちらのサイトものを題材にしていきます。このサイトでサンプルのJSONデータをJSON Schemaにしていきましょう。

JSON

{
  "checked": false,
  "dimensions": {
    "width": 5,
    "height": 10
  },
  "id": 1,
  "name": "A green door",
  "price": 12.5,
  "tags": [
    "home",
    "green"
  ]
}

JSON Scheme

{
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [     "checked",     "dimensions",
     "id",
     "name",
     "price",
     "tags"
   ],
   "properties": {
     "checked": {
       "$id": "#/properties/checked",
       "type": "boolean",
       "title": "The Checked Schema",
       "default": false,
       "examples": [
         false
       ]
     },
     "dimensions": {
       "$id": "#/properties/dimensions",
       "type": "object",
       "title": "The Dimensions Schema",
       "required": [
         "width",
         "height"
       ],
       "properties": {
         "width": {
           "$id": "#/properties/dimensions/properties/width",
           "type": "integer",
           "title": "The Width Schema",
           "default": 0,
           "examples": [
             5
           ]
         },
         "height": {
           "$id": "#/properties/dimensions/properties/height",
           "type": "integer",
           "title": "The Height Schema",
           "default": 0,
           "examples": [
             10
           ]
         }
       }
     },
     "id": {
       "$id": "#/properties/id",
       "type": "integer",
       "title": "The Id Schema",
       "default": 0,
       "examples": [
         1
       ]
     },
     "name": {
       "$id": "#/properties/name",
       "type": "string",
       "title": "The Name Schema",
       "default": "",
       "examples": [
         "A green door"
       ],
       "pattern": "^(.*)$"
     },
     "price": {
       "$id": "#/properties/price",
       "type": "number",
       "title": "The Price Schema",
       "default": 0.0,
       "examples": [
         12.5
       ]
     },
     "tags": {
       "$id": "#/properties/tags",
       "type": "array",
       "title": "The Tags Schema",
       "items": {
         "$id": "#/properties/tags/items",
         "type": "string",
         "title": "The Items Schema",
         "default": "",
         "examples": [
           "home",
           "green"
         ],
         "pattern": "^(.*)$"
       }
     }
   }
 }

少し長くてみにくいので、スッキリさせます。

"definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
     "checked",
     "id",
     "name",
     "price",
     "tags"
   ],
   "properties": {
     "checked": {
       "$id": "#/properties/checked",
       "type": "boolean",
       "title": "The Checked Schema"
     },
     "id": {
       "examples": [
         1
       ]
     },
     "name": {
       "examples": [
         "A green door"
       ],
       "pattern": "^(.*)$"
     },
     "price": {
       "examples": [
         12.5
       ]
     },
     "tags": {
         "examples": [
           "home",
           "green"
         ],
         "pattern": "^(.*)$"
       }
     }
   }

それではこちらのJSON Schemaを題材にバリテーションをかけていきましょう!

JSON Schemaにバリテーションをかけてよう!

さて、実際にバリテーションをかけていくわけですが、今回はPythonを使います!JSONで書かれたバリテーションを行う場合、かなり面倒ですよね。

ただでさえ情報量が多く可読性が低いJSONでネストされていたりいたらもう最悪ですよね。なので、今日はこの面倒な作業を簡単にしてくれるjsonschemaというPythonのパッケージを使っていきます。まずは、インストールしましょう。

pip install jsonschema

次は、コードをみていきましょう。

import jsonschema

origin_data = {
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
     "checked",
     "id",
     "name",
     "price",
     "tags"
   ],
   "properties": {
     "checked": {
     },
     "id": {
       "examples": [
         1
       ]
     },
     "name": {
       "examples": [
         "A green door"
       ],
       "pattern": "^(.*)$"
     },
     "price": {
       "examples": [
         12.5
       ]
     },
     "tags": {
         "examples": [
           "home",
           "green"
         ],
         "pattern": "^(.*)$"
       }
     }
   }


check_data = {
  "id": 2,
  "name": "A green door",
  "price": 12.5,
  "checked": False,
  "tags": [
    "home",
    "green"
  ]
}

jsonschema.validate(check_data, origin_data)

origin_dataにJSON Schemaに格納し、check_dataにチェックするためのデータを導入します。6行目に”required”されている内容が書いてあるので、その内容を含むチェックデータを導入します。実行すると、何も起きませんのでこれで正常です。

では、”price"がrequiredされているのにチェックデータに導入しなかったらどうなるでしょうか。

check_data = {
  "id": 2,
  "name": "A green door",
  #"price": 12.5,
  "checked": False,
  "tags": [
    "home",
    "green"
  ]
}

このように、priceを消して実行すると、

line 130, in validate
    raise error
jsonschema.exceptions.ValidationError: 'price' is a required property

Failed validating 'required' in schema:

このようにpriceがないよ、とバリテーションしてくれていますね。

まとめ

いかがでしたか。今日は、

  • JSON Schemaとは何か
  • どんなメリットがあるのか
  • JSON SchemaのバリテーションをPythonで書く

ということを行いました。JSON Schemaは現代のコンテナブームを考えると使えるようになっておくスキルですので是非マスターしておきましょう!それでは!!

この記事を書いた人

日向徹かこよすぎか

kaikaikai8217@gmail.com

目次