При интеграции 1С с внешними веб-сервисами разработчики часто сталкиваются с ситуацией, когда данные, отправленные в формате JSON, приходят на сторону получателя в виде нечитаемых символов (так называемых «кракозябр»). Особенно остро эта проблема проявляется при передаче кириллицы. В этой статье мы подробно разберем, почему это происходит, как проанализировать проблему и какими способами можно гарантировать корректную доставку русских символов.
Рассмотрим типичный сценарий: программист формирует JSON в 1С, устанавливает кодировку UTF-8 и отправляет пакет методом POST. Несмотря на то, что в заголовках явно указан charset=utf-8, сервер-приемник видит текст в искаженном виде, например: ÐœÑ Ð³ÐºÐ¾Ðµ пальто вместо «Мягкое пальто».
Давайте проанализируем базовый код отправки:
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос = Новый HTTPЗапрос("/", Заголовки);
// Установка тела из строки с явным указанием UTF-8 и без BOM
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
На первый взгляд, код написан абсолютно верно. Используется современный метод УстановитьТелоИзСтроки, указана целевая кодировка. Однако проблема сохраняется. Выясним причину.
Проанализируем строку ÐœÑ Ð³ÐºÐ¾Ðµ. Если пропустить её через декодеры, станет ясно, что это результат интерпретации байтов UTF-8 так, будто они являются символами кодировки ISO-8859-1 (Latin-1).
Это происходит потому, что многие веб-серверы (особенно на базе PHP или старых конфигураций Apache/Nginx) по умолчанию настроены на западноевропейские кодировки. Когда сервер получает поток байтов, он может игнорировать заголовок Content-Type и пытаться прочитать данные в своей «родной» кодировке. В итоге каждый кириллический символ, занимающий в UTF-8 два байта, превращается в два отдельных «странных» символа латиницы.
Самый надежный способ избежать проблем с кодировкой при передаче JSON — сделать так, чтобы в теле запроса вообще не было символов вне диапазона ASCII. Стандарт JSON позволяет заменять любые нелатинские символы их кодовыми последовательностями вида \uXXXX.
Например, слово «Мягкое» превратится в \u041C\u044F\u0433\u043A\u043E\u0435. Любой сервер, даже настроенный на самую экзотическую кодировку, корректно примет эти символы, так как это обычные знаки «обратный слэш», «u» и цифры.
Рассмотрим, как реализовать это в 1С с помощью объекта ЗаписьJSON:
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(,,, ВариантЭкранированияСимволов.JSON);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
// Записываем данные (структуру или соответствие)
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Теперь СтрокаJSON содержит только ASCII-символы и последовательности \uXXXX
Использование ВариантЭкранированияСимволов.JSON заставляет платформу принудительно экранировать кириллицу. Это снимает ответственность за кодировку с транспортного уровня (HTTP) и перекладывает её на уровень парсера JSON на стороне сервера.
Иногда метод УстановитьТелоИзСтроки может выполнять внутренние преобразования, зависящие от настроек платформы или операционной системы. Чтобы исключить любые влияния, проанализируем метод отправки через ДвоичныеДанные.
Разберем этот процесс по шагам:
// 1. Получаем строку (уже обсудили выше)
// 2. Преобразуем в ДвоичныеДанные (UTF-8 без BOM)
ДвоичныеДанныеТела = ПолучитьДвоичныеДанныеИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// 3. Устанавливаем тело запроса
HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеТела);
Этот метод гарантирует, что в сокет будет отправлен именно тот набор байтов, который вы подготовили, без каких-либо модификаций со стороны высокоуровневых строковых функций 1С.
Если вы контролируете серверную часть (например, пишите скрипт на PHP или Python), важно убедиться, что сервер правильно считывает поток. Проанализируем типичную ошибку на стороне PHP:
Вместо простого чтения $data = json_decode(file_get_contents('php://input')), разработчики иногда пытаются использовать функции типа utf8_decode(), которые на самом деле предназначены для преобразования из UTF-8 в ISO-8859-1, что только портит данные.
Рекомендация для серверной стороны: явно указывать обработку входящего потока как UTF-8 и проверять настройки default_charset в конфигах веб-сервера.
Проанализируем список заголовков, которые могут помочь серверу правильно распознать ваш пакет. Кроме стандартного Content-Type, полезно добавлять:
Accept: application/json — сообщает серверу, что вы ожидаете ответ в формате JSON.Accept-Charset: utf-8 — дополнительное указание на предпочтительную кодировку.Также стоит помнить, что визуальное отображение данных в логах сервера или в базе данных (например, через phpMyAdmin) часто вводит в заблуждение. Если данные в логе выглядят как «кракозябры», это не всегда означает, что они повредились при передаче. Возможно, они просто некорректно отображаются самим инструментом просмотра логов.
Подводя итог, можно выделить следующую последовательность действий при возникновении проблем с кириллицей в JSON:
ИспользованиеByteOrderMark.НеИспользовать. Большинство современных API не любят BOM-символы.\uXXXX. Это «золотой стандарт» для решения проблем совместимости.УстановитьТелоИзДвоичныхДанных для чистоты эксперимента на стороне 1С.utf8mb4 или utf8).Применяя эти подходы, мы обеспечиваем надежную интеграцию систем и исключаем потерю данных при обмене информацией.