Вводные
Требуется проверить входящие данные в HTTP сервисе в формате JSON. Использование проверки кодом сформированного вручную неудобно.
Наличие описания HTTP сервиса в формате OpenAPI https://spec.openapis.org/oas/v3.1.1.html.
Вариант решения
Получение файла схемы.
В OpenAPI версии 3.1 формат данных приведен к JSON Schema 2020-12
Типы данных в OAS основаны на типах, определённых в проекте спецификации JSON Schema Validation 2020-12: null, булево, объект, массив, число, строка или целое число. Модели определяются с помощью объекта Schema, который является расширенной версией спецификации JSON Schema 2020-12. (https://swagger.io/specification/)
поэтому для формирования схемы только требуется добавить "$schema": "https://json-schema.org/draft/2020-12/schema".
Для упрощения использования описание объектов выделяю в отдельные файлы. Выдержка из корневого файла.
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: "./Order.yml"
Описание объекта, выдержка (Order.yml)
type: object
properties:
order_id:
type: string
description: Уникальный идентификатор заказа
created_at:
type: string
format: date-time
description: "Дата создания заказа"
updated_at:
type: string
format: date-time
description: "Дата обновления заказа"
header:
description: "Заголовок заказа"
type: object
properties:
confirmation_method:
description: "Метод подтверждения заказа"
type: string
enum:
- sms
- email
- whatsapp
- phone
status:
description: "Статус заказа"
type: string
enum:
- canceled
- created
Описание в формате YAML. Для преобразования в JSON с добавлением "$schema" использую скрипт (convert.js).
const yaml = require('js-yaml');
const fs = require('fs');
filename = "Order";
// Get document, or throw exception on error
try {
const doc = yaml.load(fs.readFileSync(`./${filename}.yml`, 'utf8'));
//console.log(doc);
doc["$schema"] = "https://json-schema.org/draft/2020-12/schema";
content = JSON.stringify(doc, null, 2);
fs.writeFileSync(`./${filename}.json`, content);
} catch (e) {
console.log(e);
}
Запускаю скрипт
node convert.js
В результате получаю Order.json
{
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Уникальный идентификатор заказа"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "Дата создания заказа"
},
...
"$schema": "https://json-schema.org/draft/2020-12/schema"
}
Валидация используя схему
Для валидации использую внешнюю компоненту https://github.com/Toveal/jsonschema-1c
Схему поместил в макет.
Модуль проверки изменил под свою задачу
СхемаЗаказ = ПолучитьОбщийМакет("Заказ_Схема").ПолучитьТекст();
ТелоЗаказ = КоннекторHTTP.ОбъектВJson(СтруктураЗаказ);
БуферОшибок = ПроверитьТелоЗапроса(ТелоЗаказ, СхемаЗаказ, Отказ);
Если БуферОшибок <> Неопределено Тогда
Отказ = Истина;
СтруктураОтвет.Вставить("errors", КоннекторHTTP.JsonВОбъект(БуферОшибок));
ИначеЕсли Отказ Тогда
МассивОшибок = Новый Массив;
МассивОшибок.Добавить("Ошибка валидатора JSON");
СтруктураОтвет.Вставить("errors", МассивОшибок);
КонецЕсли;
...
Функция ПроверитьТелоЗапроса(ТелоЗаказ, СхемаЗаказ, Отказ = Ложь) Экспорт
БуферОшибок = Неопределено;
КомпонентаПодключена = ПодключитьВнешнююКомпоненту(ПутьККомпоненте(), "JsonСхема",
ТипВнешнейКомпоненты.Native, ТипПодключенияВнешнейКомпоненты.НеИзолированно);
Если Не КомпонентаПодключена Тогда
Отказ = Истина;
Возврат БуферОшибок;
КонецЕсли;
КомпонентаОбъект = Новый ("AddIn.JsonСхема.JsonSchema1C");
// Отключение доп. форматов
КомпонентаОбъект.ИспользоватьДопФорматы = Ложь;
// Установка основной схемы
Попытка
КомпонентаОбъект.УстановитьОсновнуюСхему(СхемаЗаказ);
Исключение
Сообщить(КомпонентаОбъект.ПолучитьПоследнююОшибку());
Отказ = Истина;
Возврат БуферОшибок;
КонецПопытки;
// Установка формата вывода
КомпонентаОбъект.Формат = "Ошибка: {error}, в: {path}";
// Подробная проверка
// Буфер в любом случае будет преобразован в строку
Попытка
Действителен = КомпонентаОбъект.Проверить(ТелоЗаказ, БуферОшибок);
Исключение
Сообщить(КомпонентаОбъект.ПолучитьПоследнююОшибку());
Отказ = Истина;
КонецПопытки;
Возврат БуферОшибок;
КонецФункции
Результат
Без дополнительного кода получил проверку входящих данных по актуальной версии схемы.
Для изменения валидатора нужно только поправить и сконвертировать описание сервиса.
Схема упрощенная, как использовать вложенные объекты ("$ref:") нужно разобраться.
Генераторы для приложений https://openapi-generator.tech/docs/generators не пользуют схему, а конвертируют в код на целевом языке с учетом фреймворка.
Схема OpenAPI схожа со схемой AsyncAPI https://www.asyncapi.com/docs/tutorials/getting-started/coming-from-openapi, и ту же схему можно применять при валидации для асинхронных обменов.
Благодарю за внимание.