При интеграции 1С со сторонними веб-сервисами и мобильными приложениями разработчики часто сталкиваются со специфическими требованиями к формату обмена данными. Одна из классических ситуаций — когда принимающая сторона ожидает получить данные в некорректном с точки зрения стандартов формате, например, обернуть массив объектов в «пустые» фигурные скобки без указания имени свойства: {[ ... ]}.
В этой статье мы подробно разберем, почему возникает эта проблема, рассмотрим стандарты JSON, проанализируем различные способы формирования структуры в 1С (как потоковые, так и объектные) и найдем оптимальные решения для красивой и корректной выгрузки данных.
Давайте разберем по шагам, что представляет собой формат JSON согласно международному стандарту RFC 8259. Данный формат поддерживает два основных типа коллекций:
{ }. Внутри объекта обязательно должны находиться свойства в формате "ИмяСвойства": Значение, разделенные запятыми.[ ]. Значения в нем могут быть строками, числами, объектами или другими массивами, но они пишутся через запятую без ключей.Когда мы пытаемся записать конструкцию вида {[ ... ]}, мы создаем объект (фигурные скобки), внутри которого сразу же располагается массив (квадратные скобки), минуя имя свойства. Такой формат является грубым нарушением стандарта JSON. Любой стандартный валидатор или встроенный парсер на веб-сайте выдаст ошибку: "Invalid JSON format".
Если в коде 1С попытаться записать такую структуру с помощью встроенного объекта ЗаписьJSON при стандартных настройках:
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьНачалоМассива(); // Здесь платформа вызовет исключение!
Платформа 1С сразу прервет выполнение программы с ошибкой структуры, так как свойство ПроверятьСтруктуру у объекта записи по умолчанию установлено в значение Истина.
Рассмотрим, как правильно решить эту техническую задачу тремя разными способами.
Если у вас есть возможность повлиять на разработчика принимающей стороны (веб-сайта), настоятельно рекомендуется убедить его использовать валидный JSON. Вместо генерации структуры вручную через последовательную запись свойств (потоковый метод), в 1С гораздо проще, быстрее и безопаснее использовать объектную сериализацию.
Давайте проанализируем, как переписать исходный алгоритм автора. Вместо ручного вызова методов ЗаписатьНачалоОбъекта и ЗаписатьИмяСвойства, мы соберем данные в стандартные коллекции 1С: Массив и Структура, после чего выгрузим их одной командой ЗаписатьJSON.
Для создания валидного JSON-объекта, содержащего внутри себя массив, мы дадим этому массиву понятное имя (ключ), например, "contracts". Посмотрим на пример кода:
// 1. Создаем массив для хранения наших объектов-договоров
МассивДоговоров = Новый Массив;
// Предположим, у нас есть выборка данных ВыборкаДог
Пока ВыборкаДог.Следующий() Цикл
// Каждую запись оформляем в виде отдельной структуры
ДоговорОбъект = Новый Структура;
// ВАЖНО: Ключи должны быть статичными, без добавления счетчиков (ContractNumber, а не ContractNumber1)
ДоговорОбъект.Вставить("ContractNumber", Строка(ВыборкаДог.Contract.Номер));
ДоговорОбъект.Вставить("ContractDate", ВыборкаДог.Contract.Дата);
МассивДоговоров.Добавить(ДоговорОбъект);
КонецЦикла;
// 2. Оборачиваем массив в структуру верхнего уровня для создания правильного объекта {}
ДанныеДляЭкспорта = Новый Структура;
ДанныеДляЭкспорта.Вставить("contracts", МассивДоговоров);
// 3. Выполняем быструю сериализацию в строку
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(, Символы.Таб);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
// Сериализуем объект целиком одной командой
ЗаписатьJSON(ЗаписьJSON, ДанныеДляЭкспорта);
СтрJSON = ЗаписьJSON.Закрыть();
В результате работы данного алгоритма мы получим красивый, структурированный и, самое главное, абсолютно валидный JSON-код:
{
"contracts": [
{
"ContractNumber": "XC000265Y",
"ContractDate": "2013-08-10T00:00:00"
},
{
"ContractNumber": "XC01691LY",
"ContractDate": "2018-06-10T00:00:00"
}
]
}
Обратите внимание: мы передали тип Дата напрямую в структуру без принудительного преобразования через функцию Строка(). Платформа 1С автоматически сериализовала дату в международный стандарт ISO 8601. Это значительно облегчит парсинг данных на стороне веб-сервиса.
Бывают ситуации, когда принимающий веб-сервер написан на коленке, его исходный код недоступен для изменений, а разработчик со стороны контрагента настаивает на формате {[ ... ]}.
Чтобы обойти строгие правила 1С и записать невалидный JSON программным путем, мы можем временно отключить валидацию структуры в объекте ЗаписьJSON. Для этого используется свойство ПроверятьСтруктуру. Рассмотрим этот пример подробнее:
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(, Символы.Таб);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
// Отключаем встроенную валидацию структуры платформы
ЗаписьJSON.ПроверятьСтруктуру = Ложь;
// Начинаем вывод невалидного набора скобок
ЗаписьJSON.ЗаписатьНачалоОбъекта(); // Записывает "{"
ЗаписьJSON.ЗаписатьНачалоМассива(); // Записывает "[" без ключа! Платформа промолчит.
Пока ВыборкаДог.Следующий() Цикл
ЗаписьJSON.ЗаписатьНачалоОбъекта();
// Внутренние свойства объектов записываем в стандартном режиме
ЗаписьJSON.ЗаписатьИмяСвойства("ContractNumber");
ЗаписьJSON.ЗаписатьЗначение(Строка(ВыборкаДог.Contract.Номер));
ЗаписьJSON.ЗаписатьИмяСвойства("ContractDate");
ЗаписьJSON.ЗаписатьЗначение(Формат(ВыборкаДог.Contract.Дата, "ДФ=yyyy-MM-dd"));
ЗаписьJSON.ЗаписатьКонецОбъекта();
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецМассива(); // Записывает "]"
ЗаписьJSON.ЗаписатьКонецОбъекта(); // Записывает "}"
РезультатСтрокой = ЗаписьJSON.Закрыть();
Этот метод позволяет добиться нужной последовательности скобок {[ ... ]} непосредственно при генерации потока. Однако помните, что такое решение является "костылем" и нарушает общую логику работы с форматом обмена данными.
Если вы не хотите отключать проверку структуры у ЗаписьJSON (чтобы случайно не пропустить другие критические ошибки в процессе разработки), самым простым и безопасным решением будет формирование стандартного валидного массива с его последующей текстовой оберткой.
Выясним причину, почему это безопаснее: мы поручаем платформе собрать валидный JSON-массив, гарантируя отсутствие синтаксических ошибок, а затем просто дописываем нужные символы по краям строки методами работы с текстом.
Разберем данный подход по шагам:
// Шаг 1. Формируем валидный массив объектов стандартным способом
МассивОбъектов = Новый Массив;
Пока ВыборкаДог.Следующий() Цикл
ДоговорОбъект = Новый Структура("ContractNumber, ContractDate");
ДоговорОбъект.ContractNumber = Строка(ВыборкаДог.Contract.Номер);
ДоговорОбъект.ContractDate = Формат(ВыборкаДог.Contract.Дата, "ДФ=dd.MM.yyyy");
МассивОбъектов.Добавить(ДоговорОбъект);
КонецЦикла;
// Шаг 2. Сериализуем массив в строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(, Символы.Таб));
ЗаписатьJSON(ЗаписьJSON, МассивОбъектов);
СтандартныйJSON = ЗаписьJSON.Закрыть();
// СтандартныйJSON на данный момент выглядит так:
// [
// { "ContractNumber": "...", ... }
// ]
// Шаг 3. Вручную оборачиваем полученный текст в фигурные скобки
НестандартныйJSON = "{" + Символы.ПС + СтандартныйJSON + Символы.ПС + "}";
Используя этот прием, вы гарантируете себе корректную работу сериализатора 1С во время сборки основного массива и одновременно полностью удовлетворяете специфическое требование принимающей стороны, обернув результат в фигурные скобки на самом последнем этапе.
Для того чтобы ваш код интеграции всегда оставался чистым и легко поддерживаемым, старайтесь следовать следующим правилам:
"ContractNumber1", "ContractNumber2") внутри объектов массива усложняет жизнь принимающей стороне. Массив сам по себе подразумевает индексацию элементов, поэтому имена свойств внутри объектов должны быть одинаковыми и статичными.Строка(). Для веб-приложений стандартом является ISO-формат. Используйте сериализатор 1С или функцию Формат() с маской "ДФ=yyyy-MM-ddTHH:mm:ss"."{" + "..." + "}") часто приводит к синтаксическим ошибкам, потере экранирования спецсимволов и кавычек. По возможности всегда используйте встроенные коллекции 1С и метод ЗаписатьJSON().