При интеграции между базами 1С через HTTP-сервисы или веб-сервисы часто передаются данные, полученные стандартной сериализацией платформы. В таком формате JSON содержит служебные имена полей со знаком решетки, например #type и #value.
Попытка прочитать такой документ стандартной функцией ПрочитатьJSON() без дополнительных параметров приводит к ошибке выполнения: Недопустимое имя Свойства: "#type" для чтения JSON в объект Структура. Разберем причины возникновения этой ошибки и выясним, какими способами можно корректно прочитать входящие данные.
Посмотрим на пример входящего JSON-пакета, который вызывает исключение:
{
"#type": "jcfg:CatalogObject.КакойтоСправочник",
"#value": {
"IsFolder": false,
"Ref": "eb04c6b2-fdb7-11e6-8046-000c29123d1d",
"DeletionMark": false,
"Code": "000000000001",
"Description": "Описание"
}
}
Проанализируем механику работы метода ПрочитатьJSON(). По умолчанию платформа 1С пытается преобразовать все объекты JSON в коллекцию Структура. Имена ключей в объекте Структура должны строго соответствовать правилам именования переменных встроенного языка 1С: они могут содержать только буквы, цифры и знак подчеркивания, а также не могут начинаться с цифры.
Символ # является недопустимым символом для ключа структуры, поэтому при попытке создать поле #type платформа прерывает выполнение с ошибкой.
Если в принимающей базе данных нет соответствующего объекта метаданных или требуется прочитать JSON универсальным образом как набор данных, самым простым и правильным решением будет десериализация в коллекцию Соответствие.
В отличие от структуры, ключами коллекции Соответствие могут выступать произвольные строки с любыми спецсимволами, включая #, пробелы, дефисы и точки. Для этого во второй параметр метода ПрочитатьJSON() необходимо передать значение Истина (параметр ПрочитатьВВидеСоответствия).
Разберем пример программного кода:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл(ИмяФайла);
// Второй параметр "Истина" указывает платформе читать объекты как Соответствие
РезультатJSON = ПрочитатьJSON(ЧтениеJSON, Истина);
ЧтениеJSON.Закрыть();
// Обращение к элементам выполняется через квадратные скобки
ТипОбъекта = РезультатJSON["#type"];
ДанныеОбъекта = РезультатJSON["#value"];
Если ДанныеОбъекта <> Неопределено Тогда
Код = ДанныеОбъекта["Code"];
Наименование = ДанныеОбъекта["Description"];
КонецЕсли;
Если в текущей информационной базе существует справочник или документ точно с таким же именем и структурой реквизитов, как указано в свойстве #type, можно сразу восстановить исходный объект платформы 1С. Для этого используется системный объект СериализаторXDTO.
Рассмотрим, как прочитать данные через XDTO-десериализацию:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл(ИмяФайла);
// Восстанавливаем объект конфигурации напрямую
ОбъектСправочника = СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Если тип совпал, в переменной будет готовый CatalogObject
Если ОбъектСправочника <> Неопределено Тогда
ОбъектСправочника.Записать();
КонецЕсли;
Важное ограничение: данный способ сработает только в том случае, если тип из #type объявлен в метаданных текущей конфигурации. Если конфигурации источника и приемника различаются, метод вызовет ошибку несоответствия типов XDTO.
Если входящий JSON-файл имеет большой объем и загрузка всего дерева в оперативную память нежелательна, можно воспользоваться низкоуровневым чтением узлов. Это позволяет пропустить служебные свойства заголовка и считать только полезную нагрузку.
Разберем по шагам логику потокового обхода:
ЧтениеJSON.Прочитать() для последовательного перехода по узлам.ТипТекущегоЗначения на равенство ТипУзлаJSON.ИмяСвойства.#value) считываем его значение.Закрыть().Таким образом, для чтения JSON-структур со служебными префиксами достаточно передать флаг чтения в виде соответствия ПрочитатьJSON(ЧтениеJSON, Истина) либо воспользоваться объектом СериализаторXDTO при наличии идентичных метаданных.