При работе с внешними системами и обменом данными в формате JSON разработчики 1С часто сталкиваются с ситуацией, когда стандартный механизм чтения JSON в объект Структура платформы выдает ошибку "Недопустимое имя свойства". Эта проблема возникает, когда имена свойств (ключи) в JSON-объекте не соответствуют строгим правилам именования переменных во встроенном языке 1С. В этой статье мы подробно разберем причину возникновения такой ошибки и рассмотрим, как ее корректно обрабатывать, используя объект Соответствие.
Давайте рассмотрим типичную ситуацию, описанную в нашей теме. Мы получаем JSON-ответ, содержащий объект с числовыми строковыми ключами, например, такой:
{
"distribution": {
"0": 35,
"200": 30,
"400": 18,
"600": 8,
"800": 5
}
}
При попытке прочитать этот JSON с помощью стандартного вызова:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл(ПутьКФайлу); // или ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
Ответ = ПрочитатьJSON(ЧтениеJSON);
мы получаем ошибку: "Недопустимое имя свойства: '800' для чтения JSON в объект Структура". Почему это происходит?
Для начала, важно понимать, что представленный выше JSON полностью соответствует стандарту JSON (RFC 7159). Согласно этому стандарту, имена свойств (ключи) в JSON-объектах должны быть строками и заключаться в двойные кавычки. Числовые строки, такие как "0", "200", "800", являются абсолютно корректными строковыми ключами в JSON. Стандарт не накладывает ограничений на то, что первый символ строки должен быть буквой или что она не может состоять только из цифр.
При вызове метода ПрочитатьJSON() без второго параметра, по умолчанию 1С пытается преобразовать каждый JSON-объект в объект встроенного языка типа Структура. Однако, у объекта Структура в 1С есть одно критическое ограничение: ключи (имена свойств) этой структуры должны соответствовать правилам формирования имен переменных и идентификаторов встроенного языка. Это означает, что:
Когда 1С сталкивается с ключом, таким как "800" (который начинается с цифры) или "#value" (который содержит специальный символ '#'), при попытке создать для него свойство в объекте Структура, она не может это сделать, поскольку это нарушает правила именования. Именно поэтому возникает ошибка "Недопустимое имя свойства". Платформа 1С обрабатывает JSON последовательно или с конца, и как только она натыкается на первое же недопустимое имя свойства, она выдает ошибку.
Самым правильным и рекомендуемым решением данной проблемы является использование объекта Соответствие 1С для хранения данных JSON. Соответствие, в отличие от Структуры, предназначено для хранения пар "ключ-значение", где ключи могут быть произвольными строками (или даже другими типами), и не имеют ограничений на их формат, подобно именам переменных. Это делает Соответствие идеальным инструментом для работы с JSON-объектами, чьи ключи не соответствуют строгим правилам именования Структуры в 1С.
Чтобы указать 1С читать JSON-объект в Соответствие, а не в Структуру, необходимо передать значение Истина в качестве второго параметра методу ПрочитатьJSON(). Давайте посмотрим, как это выглядит на практике:
ЧтениеJSON = Новый ЧтениеJSON;
// Пример чтения из строки
СтрокаJSON = "{""distribution"":{ ""0"":35, ""200"":30, ""400"":18, ""600"":8, ""800"":5 }}";
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
// Читаем JSON, указывая, что объекты должны быть преобразованы в Соответствия
Ответ = ПрочитатьJSON(ЧтениеJSON, Истина);
// Проверяем тип полученного объекта
Если ТипЗнч(Ответ) = Тип("Соответствие") Тогда
Сообщить("JSON успешно прочитан в Соответствие.");
Иначе
Сообщить("Что-то пошло не так. Получен объект типа: " + ТипЗнч(Ответ));
КонецЕсли;
После того как JSON прочитан в Соответствие, доступ к его элементам осуществляется не через точку (как у Структуры), а через квадратные скобки с указанием ключа в виде строки. Рассмотрим на примере нашего JSON:
// Доступ к верхнему уровню "distribution"
СоответствиеDistribution = Ответ["distribution"];
// Проверяем, что это тоже Соответствие
Если ТипЗнч(СоответствиеDistribution) = Тип("Соответствие") Тогда
Сообщить("Объект 'distribution' также является Соответствием.");
Иначе
Сообщить("Ошибка: 'distribution' не является Соответствием.");
КонецЕсли;
// Доступ к значениям по числовым строковым ключам
Значение0 = СоответствиеDistribution["0"];
Значение200 = СоответствиеDistribution["200"];
Значение800 = СоответствиеDistribution["800"];
Сообщить("Значение для ключа '0': " + Значение0); // Выведет: 35
Сообщить("Значение для ключа '200': " + Значение200); // Выведет: 30
Сообщить("Значение для ключа '800': " + Значение800); // Выведет: 5
Также можно использовать метод Получить() объекта Соответствие, что иногда может быть удобнее для цепочного вызова:
// Альтернативный способ доступа
Значение800_ЧерезПолучить = Ответ.Получить("distribution").Получить("800");
Сообщить("Значение для ключа '800' (через Получить): " + Значение800_ЧерезПолучить); // Выведет: 5
В рамках обсуждения на форуме пользователи также упоминали схожую проблему, когда при работе с пакетами XDTO и их сериализацией/десериализацией в JSON возникает ошибка "недопустимое имя свойства #value". Эта ситуация подтверждает наш вывод о проблемах Структуры с некоторыми ключами.
Когда объекты XDTO сериализуются в JSON, платформа 1С может добавлять специальные свойства, такие как #type (для указания типа XDTO-объекта) и #value (для значения, если это простой контент или текстовый узел XDTO). Если полученный таким образом JSON-файл затем пытаются прочитать обратно в Структуру, свойство #value будет расценено как недопустимое имя для свойства Структуры, вызывая описанную ошибку.
// Пример кода, вызывающего ошибку с #value при чтении в Структуру
// (гипотетический код, демонстрирующий проблему)
// ... создание МойОбъектXDTO ...
Запись = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Unix);
Запись.УстановитьСтроку(ПараметрыЗаписи);
ФабрикаXDTO.ЗаписатьJSON(Запись, МойОбъектXDTO);
ДанныеJSON = Запись.Закрыть();
обЧтениеJSON = Новый ЧтениеJSON;
обЧтениеJSON.УстановитьСтроку(ДанныеJSON);
// Этот вызов вызовет ошибку "недопустимое имя свойства #value"
// если ДанныеJSON содержит ключ #value и ПрочитатьJSON пытается создать Структуру
стСтруктураСхемы = ПрочитатьJSON(обЧтениеJSON);
Решение этой проблемы абсолютно такое же: необходимо читать такой JSON в Соответствие, используя тот же второй параметр Истина:
// Корректное чтение JSON с потенциальными ключами типа #value
обЧтениеJSON = Новый ЧтениеJSON;
обЧтениеJSON.УстановитьСтроку(ДанныеJSON);
стСоответствиеСхемы = ПрочитатьJSON(обЧтениеJSON, Истина);
// Доступ к значению #value будет выглядеть так:
Если стСоответствиеСхемы.Свойство("#value") Тогда
Сообщить("Значение XDTO: " + стСоответствиеСхемы["#value"]);
КонецЕсли;
Для эффективной работы с JSON в 1С и предотвращения ошибок "Недопустимое имя свойства" рекомендуем придерживаться следующих практик, включая автоматическую сверку бухгалтерских проводок для контроля качества обмена между информационными базами.
ПрочитатьJSON(ЧтениеJSON, Истина): Это самый надежный и универсальный подход при чтении JSON в 1С. Он гарантирует, что все JSON-объекты будут преобразованы в Соответствия, что позволяет корректно обрабатывать любые валидные ключи JSON, независимо от их формата.Соответствие для доступа к данным: После чтения JSON в Соответствие, обращайтесь к его элементам через квадратные скобки (МоеСоответствие["Ключ"]) или метод Получить() (МоеСоответствие.Получить("Ключ")).Соответствие. Вам потребуется последовательно обращаться к этим вложенным Соответствиям.Соответствия – это стандартное и корректное решение, соответствующее идеологии 1С.Используя метод ПрочитатьJSON() со вторым параметром Истина, мы обеспечиваем корректную обработку JSON-данных в 1С, избегаем распространенных ошибок "Недопустимое имя свойства" и делаем наш код более надежным и устойчивым к разнообразным форматам JSON, которые могут поступать от внешних систем. Для автоматической генерации алгоритмов разбора и проверки структуры данных пригодится инструмент для валидации JSON и генерации кода 1С.