MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  JSON スキーマ検証関数

12.18.7 JSON スキーマ検証関数

MySQL 8.0.17 以降、MySQL では、「JSON スキーマ仕様のドラフト 4」に準拠する JSON スキーマに対する JSON ドキュメントの検証がサポートされます。 これは、このセクションで説明する関数のいずれかを使用して実行できます。どちらの関数も、JSON スキーマと、スキーマに対して検証される JSON ドキュメントの 2 つの引数を取ります。 JSON_SCHEMA_VALID() は、ドキュメントがスキーマに対して検証される場合は true を返し、検証されない場合は false を返します。JSON_SCHEMA_VALIDATION_REPORT() は、検証に関する JSON 形式のレポートを提供します。

どちらの関数も、次のように NULL または無効な入力を処理します:

  • 少なくともいずれかの引数が NULL の場合、この関数は NULL を戻します。

  • 少なくともいずれかの引数が有効な JSON でない場合、関数でエラーが発生します (ER_INVALID_TYPE_FOR_JSON)

  • また、スキーマが有効な JSON オブジェクトでない場合、関数は ER_INVALID_JSON_TYPE を戻します。

MySQL では、JSON スキーマの required 属性をサポートして、必要なプロパティを強制的に含めることができます (関数の説明の例を参照)。

MySQL では、JSON スキーマの id, $schema, description および type 属性がサポートされていますが、これらは必要ありません。

MySQL では、JSON スキーマの外部リソースはサポートされていません。$ref キーワードを使用すると、JSON_SCHEMA_VALID()ER_NOT_SUPPORTED_YET で失敗します。

注記

MySQL では、JSON スキーマの正規表現パターンがサポートされています。JSON スキーマでは、無効なパターンはサポートされますが、暗黙的に無視されます (例は、JSON_SCHEMA_VALID() の説明を参照)。

これらの関数の詳細は、次のリストを参照してください:

  • JSON_SCHEMA_VALID(schema,document)

    JSON schema に対して JSON document を検証します。 schemadocument の両方が必要です。 スキーマは有効な JSON オブジェクトである必要があります。ドキュメントは有効な JSON ドキュメントである必要があります。 これらの条件が満たされている場合: ドキュメントがスキーマに対して検証される場合、関数は true (1) を戻し、それ以外の場合は false (0) を戻します。

    この例では、ユーザー変数@schema を地理座標の JSON スキーマの値に設定し、別の@document をその座標を含む JSON ドキュメントの値に設定します。 次に、JSON_SCHEMA_VALID() の引数として使用して、@document@schema に従って検証されることを確認します:

    mysql> SET @schema = '{
        '>  "id": "http://json-schema.org/geo",
        '> "$schema": "http://json-schema.org/draft-04/schema#",
        '> "description": "A geographical coordinate",
        '> "type": "object",
        '> "properties": {
        '>   "latitude": {
        '>     "type": "number",
        '>     "minimum": -90,
        '>     "maximum": 90
        '>   },
        '>   "longitude": {
        '>     "type": "number",
        '>     "minimum": -180,
        '>     "maximum": 180
        '>   }
        '> },
        '> "required": ["latitude", "longitude"]
        '>}';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> SET @document = '{
        '> "latitude": 63.444697,
        '> "longitude": 10.445118
        '>}';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT JSON_SCHEMA_VALID(@schema, @document);
    +---------------------------------------+
    | JSON_SCHEMA_VALID(@schema, @document) |
    +---------------------------------------+
    |                                     1 |
    +---------------------------------------+
    1 row in set (0.00 sec)

    @schema には required 属性が含まれているため、@document を、それ以外は有効だが必須プロパティを含まない値に設定し、次のように@schema に対してテストできます:

    mysql> SET @document = '{}';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT JSON_SCHEMA_VALID(@schema, @document);
    +---------------------------------------+
    | JSON_SCHEMA_VALID(@schema, @document) |
    +---------------------------------------+
    |                                     0 |
    +---------------------------------------+
    1 row in set (0.00 sec)

    次に示すように、@schema の値を同じ JSON スキーマに設定し、required 属性を指定しない場合、@document は、プロパティが含まれていなくても有効な JSON オブジェクトであるため検証します:

    mysql> SET @schema = '{
        '> "id": "http://json-schema.org/geo",
        '> "$schema": "http://json-schema.org/draft-04/schema#",
        '> "description": "A geographical coordinate",
        '> "type": "object",
        '> "properties": {
        '>   "latitude": {
        '>     "type": "number",
        '>     "minimum": -90,
        '>     "maximum": 90
        '>   },
        '>   "longitude": {
        '>     "type": "number",
        '>     "minimum": -180,
        '>     "maximum": 180
        '>   }
        '> }
        '>}';
    Query OK, 0 rows affected (0.00 sec)
    
    
    mysql> SELECT JSON_SCHEMA_VALID(@schema, @document);
    +---------------------------------------+
    | JSON_SCHEMA_VALID(@schema, @document) |
    +---------------------------------------+
    |                                     1 |
    +---------------------------------------+
    1 row in set (0.00 sec)

    JSON_SCHEMA_VALID() および CHECK 制約.  JSON_SCHEMA_VALID() を使用して、CHECK 制約を施行することもできます。

    次のように作成されたテーブル geo について考えてみます。JSON カラム coordinate は、このテーブルの CHECK 制約の式として渡される JSON_SCHEMA_VALID() コールで引数として使用される JSON スキーマによって制御される、マップ上の緯度と経度の点を表します:

    mysql> CREATE TABLE geo (
        ->     coordinate JSON,
        ->     CHECK(
        ->         JSON_SCHEMA_VALID(
        ->             '{
        '>                 "type":"object",
        '>                 "properties":{
        '>                       "latitude":{"type":"number", "minimum":-90, "maximum":90},
        '>                       "longitude":{"type":"number", "minimum":-180, "maximum":180}
        '>                 },
        '>                 "required": ["latitude", "longitude"]
        '>             }',
        ->             coordinate
        ->         )
        ->     )
        -> );
    Query OK, 0 rows affected (0.45 sec)
    注記

    MySQL CHECK 制約には変数への参照を含めることができないため、JSON スキーマを使用してテーブルにこのような制約を指定する場合は、JSON スキーマを JSON_SCHEMA_VALID() インラインに渡す必要があります。

    座標を表す JSON 値を次の 3 つの変数に割り当てます:

    mysql> SET @point1 = '{"latitude":59, "longitude":18}';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SET @point2 = '{"latitude":91, "longitude":0}';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SET @point3 = '{"longitude":120}';
    Query OK, 0 rows affected (0.00 sec)

    次の INSERT ステートメントに示すように、これらの最初の値は有効です:

    mysql> INSERT INTO geo VALUES(@point1);
    Query OK, 1 row affected (0.05 sec)

    2 番目の JSON 値は無効であるため、次に示すように制約は失敗します:

    mysql> INSERT INTO geo VALUES(@point2);
    ERROR 3819 (HY000): Check constraint 'geo_chk_1' is violated.

    MySQL 8.0.19 以降では、障害の性質に関する正確な情報を取得できます。この場合、latitude 値が SHOW WARNINGS ステートメントの発行によってスキーマで定義された最大値を超えています:

    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Error
       Code: 3934
    Message: The JSON document location '#/latitude' failed requirement 'maximum' at
    JSON Schema location '#/properties/latitude'.
    *************************** 2. row ***************************
      Level: Error
       Code: 3819
    Message: Check constraint 'geo_chk_1' is violated.
    2 rows in set (0.00 sec)

    必要な latitude プロパティがないため、前述の 3 番目の座標値も無効です。 以前と同様に、geo テーブルに値を挿入してから、SHOW WARNINGS を発行することで、これを確認できます:

    mysql> INSERT INTO geo VALUES(@point3);
    ERROR 3819 (HY000): Check constraint 'geo_chk_1' is violated.
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Error
       Code: 3934
    Message: The JSON document location '#' failed requirement 'required' at JSON
    Schema location '#'.
    *************************** 2. row ***************************
      Level: Error
       Code: 3819
    Message: Check constraint 'geo_chk_1' is violated.
    2 rows in set (0.00 sec)

    詳しくはセクション13.1.20.6「CHECK 制約」,をご覧ください。

    JSON スキーマでは、文字列の正規表現パターンの指定がサポートされていますが、MySQL で使用される実装では、無効なパターンは暗黙的に無視されます。 つまり、次に示すように、正規表現パターンが無効な場合でも、JSON_SCHEMA_VALID() は true を返すことができます:

    mysql> SELECT JSON_SCHEMA_VALID('{"type":"string","pattern":"("}', '"abc"');
    +---------------------------------------------------------------+
    | JSON_SCHEMA_VALID('{"type":"string","pattern":"("}', '"abc"') |
    +---------------------------------------------------------------+
    |                                                             1 |
    +---------------------------------------------------------------+
    1 row in set (0.04 sec)
  • JSON_SCHEMA_VALIDATION_REPORT(schema,document)

    JSON schema に対して JSON document を検証します。 schemadocument の両方が必要です。 JSON_VALID_SCHEMA() と同様に、スキーマは有効な JSON オブジェクトである必要があり、ドキュメントは有効な JSON ドキュメントである必要があります。 これらの条件が満たされている場合、関数は検証の結果に関するレポートを JSON ドキュメントとして返します。 JSON スキーマに従って JSON ドキュメントが有効とみなされる場合、この関数は、値が true のプロパティ valid を持つ JSON オブジェクトを戻します。 JSON ドキュメントが検証に失敗した場合、この関数は、次に示すプロパティを含む JSON オブジェクトを返します:

    • valid: スキーマ検証に失敗した場合は常に false

    • reason: 失敗の理由を含む判読可能な文字列

    • schema-location: JSON スキーマ内で検証が失敗した場所を示す JSON ポインタ URI フラグメント識別子 (このリストの後のノートを参照)

    • document-location: JSON ドキュメント内で検証が失敗した場所を示す JSON ポインタ URI フラグメント識別子 (このリストの後のノートを参照)

    • schema-failed-keyword: 違反があった JSON スキーマ内のキーワードまたはプロパティの名前を含む文字列

    注記

    JSON ポインタ URI フラグメント識別子は、「RFC 6901 - JavaScript Object Notation (JSON) ポインタ」で定義されます。 (これらは、JSON_EXTRACT() および他の MySQL JSON 関数で使用される JSON パス表記とは異なります。) この表記法では、#はドキュメント全体を表し、#/mypropmyprop という最上位プロパティに含まれるドキュメントの一部を表します。 詳細は、前述の仕様と、このセクションで後述する例を参照してください。

    この例では、ユーザー変数@schema を地理座標の JSON スキーマの値に設定し、別の@document をその座標を含む JSON ドキュメントの値に設定します。 次に、JSON_SCHEMA_VALIDATION_REORT() の引数として使用して、@document@schema に従って検証されることを確認します:

    mysql> SET @schema = '{
        '>  "id": "http://json-schema.org/geo",
        '> "$schema": "http://json-schema.org/draft-04/schema#",
        '> "description": "A geographical coordinate",
        '> "type": "object",
        '> "properties": {
        '>   "latitude": {
        '>     "type": "number",
        '>     "minimum": -90,
        '>     "maximum": 90
        '>   },
        '>   "longitude": {
        '>     "type": "number",
        '>     "minimum": -180,
        '>     "maximum": 180
        '>   }
        '> },
        '> "required": ["latitude", "longitude"]
        '>}';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> SET @document = '{
        '> "latitude": 63.444697,
        '> "longitude": 10.445118
        '>}';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT JSON_SCHEMA_VALIDATION_REPORT(@schema, @document);
    +---------------------------------------------------+
    | JSON_SCHEMA_VALIDATION_REPORT(@schema, @document) |
    +---------------------------------------------------+
    | {"valid": true}                                   |
    +---------------------------------------------------+
    1 row in set (0.00 sec)

    次に示すように、いずれかのプロパティに不正な値が指定されるように@document を設定します:

    mysql> SET @document = '{
        '> "latitude": 63.444697,
        '> "longitude": 310.445118
        '> }';

    JSON_SCHEMA_VALIDATION_REPORT() でテストすると、@document の検証が失敗するようになりました。 関数コールからの出力には、次に示すように、失敗に関する詳細情報が含まれます (より適切な書式設定を提供するために JSON_PRETTY() でラップされた関数を使用):

    mysql> SELECT JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document))\G
    *************************** 1. row ***************************
    JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document)): {
      "valid": false,
      "reason": "The JSON document location '#/longitude' failed requirement 'maximum' at JSON Schema location '#/properties/longitude'",
      "schema-location": "#/properties/longitude",
      "document-location": "#/longitude",
      "schema-failed-keyword": "maximum"
    }
    1 row in set (0.00 sec)

    @schema には required 属性が含まれているため、@document を、それ以外は有効だが必須プロパティを含まない値に設定してから、@schema に対してテストできます。 JSON_SCHEMA_VALIDATION_REPORT() の出力は、次のように、必要な要素がないために検証が失敗することを示しています:

    mysql> SET @document = '{}';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document))\G
    *************************** 1. row ***************************
    JSON_PRETTY(JSON_SCHEMA_VALIDATION_REPORT(@schema, @document)): {
      "valid": false,
      "reason": "The JSON document location '#' failed requirement 'required' at JSON Schema location '#'",
      "schema-location": "#",
      "document-location": "#",
      "schema-failed-keyword": "required"
    }
    1 row in set (0.00 sec)

    次に示すように、@schema の値を同じ JSON スキーマに設定し、required 属性を指定しない場合、@document は、プロパティが含まれていなくても有効な JSON オブジェクトであるため検証します:

    mysql> SET @schema = '{
        '> "id": "http://json-schema.org/geo",
        '> "$schema": "http://json-schema.org/draft-04/schema#",
        '> "description": "A geographical coordinate",
        '> "type": "object",
        '> "properties": {
        '>   "latitude": {
        '>     "type": "number",
        '>     "minimum": -90,
        '>     "maximum": 90
        '>   },
        '>   "longitude": {
        '>     "type": "number",
        '>     "minimum": -180,
        '>     "maximum": 180
        '>   }
        '> }
        '>}';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT JSON_SCHEMA_VALIDATION_REPORT(@schema, @document);
    +---------------------------------------------------+
    | JSON_SCHEMA_VALIDATION_REPORT(@schema, @document) |
    +---------------------------------------------------+
    | {"valid": true}                                   |
    +---------------------------------------------------+
    1 row in set (0.00 sec)

関連キーワード:  関数, schema, document, SCHEMA, スキーマ, 検証, VALID, type, longitude, latitude