При интеграции 1С со сторонними веб-сервисами, авторизации по протоколу OAuth 2.0 или взаимодействии с REST API разработчики регулярно сталкиваются с задачей извлечения конкретных полей из ответа сервера. Чаще всего ответ возвращается в виде форматированного текста JSON, содержащего служебные токены, сроки их жизни и параметры сессии.
Разберем практическую ситуацию, когда от внешнего сервиса получена следующая строка:
{"access_token":"lhgkh9fyfGfjW3tg.4sfSg0skfsk","scope":"service_program_1c","token_type":"Fresse","expires_in":1451}
Посмотрим на примеры решения данной задачи различными способами: с помощью стандартных объектов платформы 1С, компактных методов современных версий и готовых библиотечных функций.
Рассмотрим классический механизм платформы, доступный практически во всех релизах 1С:Предприятие 8.3. Для десериализации применяется связка специализированного объекта чтения потока и функции глобального контекста.
Обратим внимание на частую ошибку: сам по себе объект ЧтениеJSON лишь инициализирует поток чтения и не возвращает готовую структуру данных. Чтобы преобразовать данные в коллекцию 1С, необходимо передать этот поток в метод ПрочитатьJSON.
Разберем по шагам правильную реализацию десериализации:
ЧтениеJSON и связываем его со строкой через метод УстановитьСтроку.ПрочитатьJSON в переменную.Закрыть.Посмотрим на программный код:
СтрокаJSON = "{""access_token"":""lhgkh9fyfGfjW3tg.4sfSg0skfsk"",""scope"":""service_program_1c"",""token_type"":""Fresse"",""expires_in"":1451}";
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(СтрокаJSON);
СтруктураJSON = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
// Безопасное получение значений через метод Свойство
Токен = "";
Если СтруктураJSON.Свойство("access_token", Токен) Тогда
Сообщить("Получен токен: " + Токен);
КонецЕсли;
ТипТокена = "";
Если СтруктураJSON.Свойство("token_type", ТипТокена) Тогда
Сообщить("Тип токена: " + ТипТокена);
КонецЕсли;
Проанализируем современный подход, появившийся в релизах платформы начиная с 8.3.23. Разработчикам больше не требуется вручную создавать и закрывать поток ЧтениеJSON для простых строковых данных. Достаточно вызвать метод ПрочитатьЗначениеJSON, передав строку напрямую.
Посмотрим, насколько лаконичным становится код:
СтрокаJSON = "{""access_token"":""lhgkh9fyfGfjW3tg.4sfSg0skfsk"",""scope"":""service_program_1c"",""token_type"":""Fresse"",""expires_in"":1451}";
СтруктураJSON = ПрочитатьЗначениеJSON(СтрокаJSON);
ЗначениеТокена = СтруктураJSON.access_token;
ЗначениеТипа = СтруктураJSON.token_type;
Сообщить("Токен: " + ЗначениеТокена);
Сообщить("Тип: " + ЗначениеТипа);
Важно: метод ПрочитатьЗначениеJSON удобен еще и тем, что доступен в любом контексте выполнения, включая клиентские модули и веб-клиент.
Если разработка ведется в типовой конфигурации на базе БСП, мы можем воспользоваться универсальными методами общих модулей. Это избавляет от необходимости писать низкоуровневый код разбора потоков.
В переписке упоминается модуль ЭлектроннаяПодписьВМоделиСервиса, однако использовать узкоспециализированные подсистемы для общей работы не рекомендуется, так как они могут отсутствовать в вашей конфигурации. Вместо этого разберем стандартные вызовы:
// Вариант 1: через модуль РаботаСJSON
СтруктураJSON = РаботаСJSON.ПрочитатьJSON(СтрокаJSON);
// Вариант 2: через модуль ОбщегоНазначенияКлиентСервер
СтруктураJSON = ОбщегоНазначенияКлиентСервер.JSONВЗначение(СтрокаJSON);
Токен = СтруктураJSON.access_token;
Выясним причину возможных сбоев при десериализации JSON и рассмотрим способы защиты от них:
Структура требует, чтобы имена ключей соответствовали правилам идентификаторов 1С. Если сервис вернет ключ с дефисом (например, "access-token"), попытка преобразования в структуру завершится аварийной ошибкой. Чтобы избежать этого, укажем второй параметр Истина в методе ПрочитатьJSON, чтобы десериализация произошла в объект Соответствие:
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(СтрокаJSON);
Данные = ПрочитатьJSON(Чтение, Истина); // Читаем в Соответствие
Чтение.Закрыть();
Токен = Данные["access-token"];
Структура в 1С нечувствительна к регистру. Если ответ содержит ключи token и Token, чтение в структуру вызовет конфликт. Использование объекта Соответствие полностью решает эту проблему.СтруктураJSON.access_token) отсутствие ключа в ответе приведет к ошибке «Поле объекта не обнаружено». Рекомендуется всегда использовать метод Свойство() для безопасного извлечения значений.