При разработке интеграций с внешними сервисами, такими как Яндекс.Маркет, программисты 1С часто сталкиваются с ошибкой «Непредвиденный символ при чтении JSON». Эта ситуация особенно коварна тем, что сервер возвращает код состояния 200 (OK), подтверждая успешность запроса, но встроенная функция 1С ПрочитатьJSON() аварийно завершает работу. В данной статье мы подробно разберем, почему это происходит и как правильно настроить обмен данными, чтобы избежать подобных сбоев.
Первым делом проанализируем ситуацию, в которой возникает ошибка. Рассмотрим стандартный фрагмент кода, который обычно приводит к проблеме:
Ответ = HTTPОтвет.ПолучитьТелоКакСтроку("UTF-8");
Если HTTPОтвет.КодСостояния = 200 Тогда
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ);
ПараметрыJSON = ПрочитатьJSON(ЧтениеJSON); // Ошибка вылетает здесь
КонецЕсли;
Основная причина ошибки «Непредвиденный символ» заключается в том, что содержимое переменной Ответ на самом деле не является валидным JSON-объектом. Как показывает практика интеграции с API Яндекса, сервер может вернуть ответ в формате XML, если в запросе явно не указано иное. Посмотрим на пример «битого» ответа, который получает автор темы:
<response><status>OK</status><result><paging next-page-token="..."/>...
Поскольку XML начинается с символа <, парсер ЧтениеJSON моментально выдает исключение, так как ожидает увидеть открывающую фигурную скобку { или квадратную скобку [. Таким образом, проблема не в «плохом» символе внутри данных, а в неверном формате всего пакета данных.
Для того чтобы Яндекс.Маркет возвращал данные именно в формате JSON, необходимо правильно сконфигурировать заголовки HTTPЗапрос. Разберем два ключевых заголовка:
application/json.Рассмотрим пример правильной подготовки запроса в 1С:
ЗаголовокЗапроса = Новый Соответствие;
// Указываем, что хотим получить JSON
ЗаголовокЗапроса.Вставить("Accept", "application/json");
// Указываем, что отправляем JSON (если есть тело запроса)
ЗаголовокЗапроса.Вставить("Content-Type", "application/json");
HTTPЗапрос = Новый HTTPЗапрос(Ресурс, ЗаголовокЗапроса);
Важный нюанс: Многие ошибочно устанавливают только Content-Type, забывая про Accept. Если сервер по умолчанию настроен на выдачу XML, без заголовка Accept вы продолжите получать ошибки парсинга.
Часто возникает ситуация, когда первая порция данных (например, первые 100 товаров) обрабатывается успешно, а на следующей странице снова возникает ошибка. Выясним причину этого поведения.
В API Яндекса используется механизм токенов для постраничного вывода. Когда мы запрашиваем следующую страницу, мы создаем новый HTTPЗапрос. Типичная ошибка программиста — не продублировать заголовки Accept и Content-Type во втором и последующих запросах. В этом случае сервер «забывает», что вы работали с JSON, и возвращает следующую порцию данных в формате по умолчанию (XML).
Проанализируем алгоритм работы с токеном:
// В цикле получения страниц
Пока ЗначениеЗаполнено(ТекущийТокен) Цикл
ЗапросСледующейСтраницы = Новый HTTPЗапрос(ПутьСПараметромТокена);
// ОБЯЗАТЕЛЬНО добавляем заголовки повторно!
ЗапросСледующейСтраницы.Заголовки.Вставить("Accept", "application/json");
Ответ = Соединение.ВызватьHTTPМетод("GET", ЗапросСледующейСтраницы);
// ... обработка ответа
КонецЦикла;
Если вы убедились, что ответ приходит в формате JSON (строка начинается с {), но ошибка «Непредвиденный символ» сохраняется на первой же позиции, скорее всего, в начале строки присутствует BOM (Byte Order Mark) — невидимый маркер кодировки UTF-8.
Разберем, как очистить строку от нежелательных символов перед началом парсинга. Рассмотрим следующий код:
ТелоСтрокой = HTTPОтвет.ПолучитьТелоКакСтроку();
// Удаляем BOM (символ с кодом 65279), если он есть
СимволBOM = Символ(65279);
Пока Лев(ТелоСтрокой, 1) = СимволBOM Цикл
ТелоСтрокой = Сред(ТелоСтрокой, 2);
КонецЦикла;
// Дополнительно можно обрезать лишние пробелы по краям
ТелоСтрокой = СокрЛП(ТелоСтрокой);
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоСтрокой);
Также следует помнить, что в описаниях товаров (которые хранит Яндекс) могут встречаться неэкранированные управляющие символы (например, «битые» переносы строк с ASCII-кодами ниже 32). Если такие символы попадают внутрь JSON-строки, парсер 1С может их не пропустить. В этом случае полезно проанализировать тело ответа в текстовом редакторе, поддерживающем отображение невидимых символов (например, Notepad++ или VS Code).
Чтобы быстро найти проблемное место в большом объеме данных, выполните следующие шаги:
HTTPОтвет.ПолучитьТелоКакДвоичныеДанные() в файл на диске. Это позволит вам изучить «сырые» данные без искажений со стороны отладчика 1С.ПрочитатьJSON(ЧтениеJSON), которая читает весь объект целиком, используйте цикл с методом ЧтениеJSON.Прочитать(). Это позволит вам увидеть, на каком именно товаре или свойстве парсер «споткнулся».ПрочитатьJSON вторым параметром рекомендуется передавать Истина (читать в соответствие). Это делает структуру данных более предсказуемой при работе с динамическими ключами, которые могут встречаться в API маркетплейсов.Подводя итог, можно сказать, что интеграция с Яндекс.Маркетом требует строгого соблюдения протокола HTTP. Правильная установка заголовка Accept: application/json и внимательное отношение к повторным запросам при пагинации — залог стабильной работы вашего кода и отсутствия ошибок «непредвиденного символа».