14.17.7 Функции валидации JSON-схем
MySQL поддерживает валидацию JSON-документов по JSON-схемам, соответствующим Спецификации JSON-схемы Draft 4. Это можно сделать, используя одну из функций, описанных в этом разделе, обе из которых принимают два аргумента: 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по JSONschema. Оба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, созданную, как показано здесь, со столбцом JSONcoordinate, представляющим точку широты и долготы на карте, управляемым 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)ПримечаниеПоскольку ограничение MySQL
CHECKне может содержать ссылок на переменные, вы должны передавать 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.21.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
documentпо JSONschema. Оба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.