Как правильно читать JSON в 1С при наличии динамических ключей и вложенных массивов

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними API (например, криптобиржами, картографическими сервисами или социальными сетями) разработчики часто сталкиваются с форматом JSON, структура которого не является статичной. Ошибки возникают на этапе попытки преобразовать «гибкий» JSON в «жесткую» модель данных XDTO. В этой статье мы подробно разберем, почему возникают ошибки валидации и как правильно организовать чтение сложных структур данных.

Проблема 1: Динамические ключи в структуре JSON

Рассмотрим ситуацию, когда в JSON-ответе ключи объектов являются данными, а не именами полей. Например, map0, map1, map2 и так далее. Проанализируем типичный пример кода, который вызывает ошибку:


ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(пСтрока);
// Попытка прочитать через фабрику с указанием типа
ОбъектXDTO = ФабрикаXDTO.ПрочитатьJSON(ЧтениеJSON, ФабрикаXDTO.Тип("http://mapssssss.ru", "info"));

В данном случае платформа выдает ошибку: "Структура объекта не соответствует типу. map0 — это одновременно и имя элемента и значение". Выясним причину этого поведения. Механизм XDTO (XML Data Transfer Objects) основан на строгой схеме. Когда мы указываем конкретный тип ФабрикаXDTO.Тип(...), система ожидает, что в JSON будут только те свойства, которые описаны в пакете XDTO. Если в данных приходят ключи типа map0, которые не зафиксированы в схеме как свойства, XDTO не понимает, как их интерпретировать. В XDTO невозможно (без сложных манипуляций с anyType) описать объект, ключи которого заранее неизвестны.

Проблема 2: Вложенные массивы (Array of Arrays)

Другой распространенный сценарий — передача координат или значений в виде массивов без ключей, например: "plus": [[104.67, 0.01], [104.75, 11]]. При попытке прочитать такой JSON через ФабрикаXDTO.ПрочитатьJSON() часто возникает критическая ошибка или исключение "Недопустимое значение аргумента функции".

Проанализируем ситуацию: в модели XDTO массив — это список элементов определенного типа. Однако анонимный вложенный массив [104.67, 0.01] не имеет имени тега (как это было бы в XML), и фабрика XDTO не может сопоставить его ни с одним свойством объекта, если структура не описана филигранно точно. Более того, на старых версиях платформы (например, 8.3.12) такие попытки приводили к аварийному завершению работы клиента.

Решение: Глобальная функция ПрочитатьJSON()

Для работы с динамическими структурами наиболее эффективным и стабильным решением является использование глобальной функции ПрочитатьJSON(). В отличие от метода фабрики XDTO, эта функция не требует предварительного описания схемы и преобразует JSON в стандартные коллекции 1С: Структура, Соответствие или Массив.

Разберем по шагам правильный алгоритм чтения:

  1. Создаем объект ЧтениеJSON.
  2. Загружаем в него строку или открываем файл.
  3. Используем универсальный метод чтения в коллекции 1С.

Посмотрим на пример реализации:


// Подготовим строку JSON
ОтветJSON = "{
    ""map0"":{
        ""plus"":[[104.67, 0.01], [104.75, 11]],
        ""minus"":[[104.3, 5.36], [104.21, 2.57]]
    }
}";

ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ОтветJSON);

// Правильный способ чтения динамических данных
Данные = ПрочитатьJSON(ЧтениеJSON); 

// Теперь мы можем обращаться к данным как к обычным коллекциям 1С
Для Каждого КлючИЗначение Из Данные.map0.plus Цикл
    // КлючИЗначение будет массивом с двумя элементами [104.67, 0.01]
    КоординатаX = КлючИЗначение[0];
    КоординатаY = КлючИЗначение[1];
КонецЦикла;

ЧтениеJSON.Закрыть();

Выясним разницу: ПрочитатьJSON vs ФабрикаXDTO.ПрочитатьJSON

Разберем подробнее, в чем техническое различие между этими двумя подходами, чтобы понимать, когда какой использовать:

1. Глобальная функция ПрочитатьJSON():

2. Метод ФабрикаXDTO.ПрочитатьJSON():

Практические советы по работе с данными

При работе с большими числами или специфическими форматами дат (например, ISO 8601), стандартная функция ПрочитатьJSON() позволяет использовать «функцию обработки данных». Это дает возможность вручную преобразовать строку в нужный тип данных 1С прямо в процессе парсинга.

Рассмотрим пример использования функции обработки:


Функция МояФункцияОбработки(Свойство, Значение, ДополнительныеПараметры, Отказ)
    // Если поле называется "server_time", преобразуем его из Unix Timestamp в Дату 1С
    Если Свойство = "server_time" Тогда
        Возврат Дата(1970, 1, 1, 1, 1, 1) + Значение;
    КонецЕсли;
    Возврат Значение;
КонецФункции

// При чтении указываем имя функции обработки
Данные = ПрочитатьJSON(ЧтениеJSON, Ложь, , "МояФункцияОбработки");

Важный момент: Если вы столкнулись с ошибкой в платформе 8.3.12 или более ранних, настоятельно рекомендуем обновить платформу до актуальных версий (8.3.15+). В них работа парсера JSON была существенно оптимизирована, добавлены проверки на корректность аргументов, что предотвращает «вылеты» клиента при получении битых или неожиданных структур от сервера.

Таким образом, для интеграции с внешними веб-сервисами, отдающими динамические ключи (как в примерах с картами или биржами), всегда выбирайте глобальную функцию ПрочитатьJSON. Это обеспечит стабильность вашей конфигурации и упростит дальнейшую поддержку кода.

← На главную