Spec-Zone.ru › MySQL 8.4

14.17.7 Функции валидации JSON-схем

MySQL поддерживает валидацию JSON-документов по отношению к JSON-схемам, соответствующим черновику 4 спецификации JSON Schema. Это можно сделать, используя любую из функций, подробно описанных в этом разделе, обе из которых принимают два аргумента: JSON-схему и JSON-документ, который валидируется по отношению к схеме. JSON_SCHEMA_VALID() возвращает true, если документ валиден по отношению к схеме, и false, если нет; JSON_SCHEMA_VALIDATION_REPORT() предоставляет отчёт в формате JSON о валидации.

Обе функции обрабатывают null или некорректные входные данные следующим образом:

  • Если хотя бы один из аргументов — NULL, функция возвращает NULL.

  • Если хотя бы один из аргументов не является валидным JSON, функция вызывает ошибку.

  • Кроме того, если схема не является валидным JSON-объектом, функция возвращает .

MySQL поддерживает атрибут required в JSON-схемах для принудительного включения требуемых свойств (см. примеры в описаниях функций).

MySQL поддерживает атрибуты id, $schema, description и type в JSON-схемах, но не требует ни одного из них.

MySQL не поддерживает внешние ресурсы в JSON-схемах; использование ключевого слова $ref приводит к тому, что JSON_SCHEMA_VALID() завершается с ошибкой.

Примечание

MySQL поддерживает шаблоны регулярных выражений в JSON-схемах, которые поддерживаются, но при этом некорректные шаблоны игнорируются (см. описание JSON_SCHEMA_VALID() для примера).

Эти функции подробно описаны в следующем списке:

  • JSON_SCHEMA_VALID(schema,document)

    Валидирует JSON document по отношению к JSON schema. И schema, и document являются обязательными. Схема должна быть валидным JSON-объектом; документ должен быть валидным JSON-документом. При соблюдении этих условий: если документ валиден по отношению к схеме, функция возвращает true (1); в противном случае — false (0).

    В этом примере мы устанавливаем переменную пользователя @schema со значением JSON-схемы для географических координат и другую переменную @document со значением JSON-документа, содержащего такие координаты. Затем мы проверяем, что @document валиден по отношению к @schema, используя их как аргументы для JSON_SCHEMA_VALID():

    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, представляющим точку широты и долготы на карте, управляемую JSON-схемой, используемой в качестве аргумента в вызове JSON_SCHEMA_VALID(), который передаётся как выражение ограничения CHECK для этой таблицы:

    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)
    
    Примечание

    Поскольку ограничение CHECK в MySQL не может содержать ссылки на переменные, вам необходимо передать JSON-схему в JSON_SCHEMA_VALID() непосредственно при использовании её для задания такого ограничения для таблицы.

    Мы присваиваем JSON-значения, представляющие координаты, трём переменным, как показано здесь:

    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)
    

    Второе JSON-значение не является валидным и поэтому не проходит проверку, как показано здесь:

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

    Вы можете получить точную информацию о природе ошибки — в данном случае, что значение 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. Как и прежде, вы можете увидеть это, попытавшись вставить значение в таблицу 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)
    

    См. Раздел 15.1.20.6, «Ограничения CHECK» для получения дополнительной информации.

    JSON Schema поддерживает указание шаблонов регулярных выражений для строк, но реализация, используемая 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 document по отношению к JSON schema. И schema, и document являются обязательными. Как и в случае с JSON_VALID_SCHEMA(), схема должна быть валидным JSON-объектом, а документ — валидным JSON-документом. При соблюдении этих условий функция возвращает отчёт (как JSON-документ) о результатах валидации. Если JSON-документ считается валидным по отношению к JSON-схеме, функция возвращает JSON-объект с одним свойством valid, имеющим значение "true". Если JSON-документ не проходит валидацию, функция возвращает JSON-объект, включающий свойства, перечисленные здесь:

    • valid: Всегда "false" для невалидной валидации по отношению к схеме

    • reason: Читабельная строка, содержащая причину ошибки

    • schema-location: URI-фрагмент JSON-указателя, указывающий, где в JSON-схеме произошла ошибка валидации (см. Примечание после этого списка)

    • document-location: URI-фрагмент JSON-указателя, указывающий, где в JSON-документе произошла ошибка валидации (см. Примечание после этого списка)

    • schema-failed-keyword: Строка, содержащая имя ключевого слова или свойства в JSON-схеме, нарушенного ограничением

    Примечание

    URI-фрагменты JSON-указателей определены в RFC 6901 - JavaScript Object Notation (JSON) Pointer. (Эти указатели не совпадают с обозначением JSON-путей, используемых функциями JSON_EXTRACT() и другими JSON-функциями MySQL.) В этой нотации # представляет весь документ, а #/myprop представляет часть документа, включённую в свойство верхнего уровня, имеющее имя myprop. Смотрите процитированную спецификацию и примеры, показанные позже в этом разделе, для получения дополнительной информации.

    В этом примере мы устанавливаем переменную пользователя @schema со значением JSON-схемы для географических координат и другую переменную @document со значением JSON-документа, содержащего такие координаты. Затем мы проверяем, что @document валиден по отношению к @schema, используя их как аргументы для JSON_SCHEMA_VALIDATION_REORT():

    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
        '> }';
    

    Валидация @document теперь терпит неудачу при проверке с помощью JSON_SCHEMA_VALIDATION_REPORT(). Вывод из вызова функции содержит подробную информацию об ошибке (с функцией, обернутой функцией 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)
    

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/json-validation-functions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API