Работа с форматом JSON в 1С:Предприятии 8.3 обычно не вызывает сложностей, пока мы придерживаемся стандартных протоколов обмена. Однако на практике часто встречаются ситуации, когда внешние системы (API) предъявляют специфические требования к формату данных. Одной из наиболее частых проблем является автоматическое экранирование двойных кавычек (превращение " в \") и символов переноса строки (превращение в \n) внутри строковых значений. Разберем подробно, почему так происходит и какими способами можно добиться нужного результата.
Прежде всего, проанализируем ситуацию с точки зрения стандартов. Согласно спецификации JSON (RFC 8259), двойная кавычка внутри строки является зарезервированным символом. Чтобы парсер на принимающей стороне мог отличить кавычку, закрывающую строку, от кавычки внутри текста, последняя обязана быть экранирована обратным слешем. Платформа 1С строго следует этому стандарту. Когда мы используем метод ЗаписатьЗначение() объекта ЗаписьJSON, система гарантирует валидность итогового файла, автоматически обрабатывая все опасные символы.
Рассмотрим стандартный код, который вызывает «проблему» у автора темы:
ТекстXML = Новый ТекстовыйДокумент;
ТекстXML.ДобавитьСтроку("<?xml version=1.0 encoding=""WINDOWS-1251"" ?>");
ТекстДляЗаписи = ТекстXML.ПолучитьТекст();
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписьJSON.ЗаписатьИмяСвойства("xmlStr");
ЗаписьJSON.ЗаписатьЗначение(ТекстДляЗаписи);
СтрJSON = ЗаписьJSON.Закрыть();
// Результат: "xmlStr": "<?xml version=1.0 encoding=\"WINDOWS-1251\" ?>\n"
Здесь мы видим сразу две особенности: появление \" вместо кавычек и \n в конце строки. Выясним причины и способы решения для каждого случая.
Многие разработчики в первую очередь пытаются настроить объект ПараметрыЗаписиJSON. Платформа предоставляет достаточно широкий набор настроек для управления экранированием. Проанализируем возможности этого метода:
ПараметрыJSON = Новый ПараметрыЗаписиJSON(
ПереносСтрокJSON.Нет,
" ",
Истина, // ИспользоватьДвойныеКавычки
ЭкранированиеСимволовJSON.Нет,
Ложь, // ЭкранироватьУгловыеСкобки
Ложь, // ЭкранироватьРазделителиСтрок
Ложь, // ЭкранироватьАмперсанд
Ложь, // ЭкранироватьОдинарныеКавычки
Ложь // ЭкранироватьСлеш
);
ЗаписьJSON.ОткрытьСтроку(ПараметрыJSON);
Важное замечание: Настройка ЭкранированиеСимволовJSON.Нет отключает только преобразование Unicode-символов (например, кириллицы) в последовательности \uXXXX. Она не отменяет обязательное экранирование двойных кавычек, так как это нарушило бы базовую структуру JSON. Таким образом, только лишь параметрами записи задачу «чистых кавычек» внутри строки решить невозможно.
Если API на стороне получателя написано «на коленке» и не умеет обрабатывать стандартные экранированные последовательности, нам приходится идти на хитрость. В 1С существует метод ЗаписатьБезОбработки(). Он позволяет вставить в поток JSON любую строку «как есть», минуя механизмы контроля платформы.
Посмотрим, как правильно применить этот метод, чтобы сохранить структуру JSON, но передать нужные символы. Основная сложность здесь заключается в том, что нам нужно самостоятельно добавить обрамляющие кавычки для строкового значения:
ТекстДляЗаписи = "<?xml version=""1.0"" encoding=""WINDOWS-1251"" ?>"; // Без лишних переносов строк
ЗаписьJSON.ЗаписатьИмяСвойства("xmlStr");
// Вариант с ручным обрамлением кавычками
ЗаписьJSON.ЗаписатьБезОбработки("""" + ТекстДляЗаписи + """");
При использовании этого метода нужно быть крайне осторожными. Если внутри переменной ТекстДляЗаписи встретится символ, который действительно должен быть экранирован (например, если там будет сложный XML с вложенными данными), итоговый JSON-файл может стать невалидным и не прочитается ни одним стандартным парсером. Для диагностики и исправления таких поврежденных строк пригодится инструмент для восстановления невалидного JSON.
Это наиболее профессиональный и надежный способ передачи вложенных документов (XML, HTML, бинарных файлов) внутри JSON. Вместо того чтобы бороться с кавычками и кодировками, мы преобразуем весь вложенный текст в строку Base64. Этот формат состоит только из латинских букв и цифр, что исключает любые конфликты с синтаксисом JSON.
Разберем пример реализации:
// 1. Превращаем строку XML в двоичные данные (с учетом нужной кодировки)
ДвоичныеДанныеXML = ПолучитьДвоичныеДанныеИзСтроки(ТекстXML, "windows-1251");
// 2. Кодируем в Base64
СтрокаBase64 = Base64Строка(ДвоичныеДанныеXML);
// 3. Записываем в JSON стандартным способом
ЗаписьJSON.ЗаписатьИмяСвойства("xmlStrBase64");
ЗаписьJSON.ЗаписатьЗначение(СтрокаBase64);
Этот подход требует поддержки на принимающей стороне: получатель должен знать, что поле xmlStrBase64 нужно сначала декодировать из Base64, а уже потом обрабатывать как XML. Это стандарт де-факто в современной разработке.
Автор вопроса столкнулся с тем, что в JSON попадает символ \n. Это происходит из-за использования объекта ТекстовыйДокумент. Метод ДобавитьСтроку() всегда добавляет невидимый символ перевода строки в конец. При записи в JSON этот символ превращается в управляющую последовательность.
Чтобы этого избежать, проанализируем два способа очистки данных:
СтрЗаменить(Текст, Символы.ПС, "").ЗаписьXML и ЗаписьJSON напрямую, не используя промежуточные текстовые документы, которые добавляют лишнее форматирование.Пример очистки строки:
ТекстДляЗаписи = ТекстXML.ПолучитьТекст();
// Удаляем переносы строк и лишние пробелы по краям
ТекстДляЗаписи = СтрЗаменить(ТекстДляЗаписи, Символы.ПС, "");
ТекстДляЗаписи = СтрЗаменить(ТекстДляЗаписи, Символы.ВК, "");
ТекстДляЗаписи = СокрЛП(ТекстДляЗаписи);
ЗаписьJSON.ЗаписатьЗначение(ТекстДляЗаписи);
Выясним еще один важный нюанс. JSON по стандарту всегда передается в кодировке UTF-8. Если внутри строки вы указываете encoding="WINDOWS-1251", это может создать техническое противоречие.
Если вы передаете XML внутри JSON-строки, фактически этот XML уже представлен в кодировке UTF-8 (как часть общего документа). Поэтому декларация encoding="WINDOWS-1251" внутри строки может сбить с толку парсер на другой стороне. Рассмотрим рекомендации:
Подведем итог нашему исследованию. Для корректной работы со спецсимволами в JSON выберите один из путей:
\"). Это правильный JSON. Если принимающая сторона его не понимает — проблема в парсере на той стороне.ЗаписатьБезОбработки(), самостоятельно добавляя внешние кавычки и предварительно очищая строку от символов Символы.ПС.Помните, что ручное формирование JSON или использование методов «без обработки» — это крайняя мера, которая перекладывает ответственность за валидность данных на разработчика 1С. Для валидации структуры и генерации корректного кода работы с данными можно использовать инструмент для форматирования и проверки JSON.