Непредвиденный символ при чтении JSON в 1С: диагностика ошибки ПрочитатьJSON
«Непредвиденный символ при чтении JSON» — это ошибка парсера ПрочитатьJSON,
которую 1С 8.3 бросает, когда встречает байт вне грамматики JSON. Проверьте по порядку:
BOM в начале строки/файла (символ с кодом 65279, байты EF BB BF),
кодировку ответа (UTF-8, а не windows-1251) и что сервер
действительно вернул JSON, а не HTML-страницу ошибки или XML.
Позицию символа удобно смотреть через свойства ТекущаяСтрока и
ТекущаяПозиция объекта ЧтениеJSON в блоке
Попытка…Исключение. Если строка приходит от внешнего HTTP-сервиса —
сначала сохраните её в файл и прогоните через онлайн-валидатор
(jsonlint), это в разы ускоряет диагностику.
Причина №1: BOM в начале файла или строки
Самая частая причина ошибки «непредвиденный символ при чтении json 1с» — метка порядка байтов
(Byte Order Mark, BOM). Это три байта EF BB BF в начале UTF-8 файла, невидимые
в текстовом редакторе, но JSON-грамматика их не допускает: JSON должен начинаться с
{, [, ", цифры, true, false
или null. Парсер ПрочитатьJSON видит невидимый символ и падает
на позиции 1.
Если данные пришли строкой, уберите BOM через СтрЗаменить с символом 65279:
Функция УдалитьBOM(Строка)
Возврат СтрЗаменить(Строка, Символ(65279), "");
КонецФункции
// Использование:
Ответ = HTTPОтвет.ПолучитьТелоКакСтроку("UTF-8");
Ответ = УдалитьBOM(Ответ);
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ);
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
ЧтениеJSON.Закрыть();
Второй сценарий — читаем файл с диска, в котором «зашит» BOM. Здесь помогает промежуточное
чтение через ЧтениеТекста с явной кодировкой: 1С сама пропускает BOM для
UTF-8, если кодировку указать корректно.
Чтение = Новый ЧтениеТекста;
Чтение.Открыть("C:\Exchange\data.json", "UTF-8");
СтрокаJSON = Чтение.Прочитать();
Чтение.Закрыть();
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрЗаменить(СтрокаJSON, Символ(65279), ""));
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
При формировании JSON на стороне 1С (например, тело HTTP-ответа) укажите
ИспользованиеByteOrderMark.НеИспользовать при получении строки — это стандартная
рекомендация 1С для JSON, чтобы принимающая сторона не столкнулась с той же проблемой.
В Консоли кода AI-агент видит и код чтения JSON, и живой ответ внешнего сервиса: он сам находит BOM, «умные» кавычки и подсказывает, нужно ли читать в Соответствие или Структуру — без ручной отладки в конфигураторе.
Попросите агента: «Мой ПрочитатьJSON падает на первом символе — покажи, есть ли BOM в ответе HTTP-сервиса, и как его убрать перед разбором».Причина №2: неверная кодировка (cp1251 вместо UTF-8)
Вторая по частоте причина ошибки «1с прочитатьjson» — кодировка. JSON по стандарту RFC 8259 всегда в Unicode (по умолчанию UTF-8). Если внешний сервис отдаёт cp1251, а вы читаете тело как UTF-8, кириллические байты превращаются в мусор и парсер падает на первом «сломанном» символе внутри строки.
Как проверить и починить:
// Смотрим заголовок Content-Type
Заголовок = HTTPОтвет.Заголовки["Content-Type"]; // "application/json; charset=windows-1251"
// Если сервер честно указал charset — берём именно его
Ответ = HTTPОтвет.ПолучитьТелоКакСтроку("windows-1251");
// Если Content-Type не указан, но данные явно битые — попробуйте обе кодировки
Попытка
Ответ = HTTPОтвет.ПолучитьТелоКакСтроку("UTF-8");
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ);
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
Исключение
Ответ = HTTPОтвет.ПолучитьТелоКакСтроку("windows-1251");
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ);
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
КонецПопытки;
Если работаете с файлом — вместо ЧтениеJSON.ОткрытьФайл() без параметров
используйте вариант с явной кодировкой:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл("C:\Exchange\data.json", "UTF-8");
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
ЧтениеJSON.Закрыть();
Причина №3: сервер вернул не JSON, а HTML или XML
Классический кейс с форумов mista и infostart: HTTP-запрос возвращает
КодСостояния = 200, но в теле — HTML-страница с ошибкой авторизации,
капча, редирект или XML. ЧтениеJSON видит < первым
символом и сообщает «непредвиденный символ при чтении json 1с ошибка» на позиции 1.
Всегда логируйте первые 200 символов ответа перед разбором:
Ответ = HTTPОтвет.ПолучитьТелоКакСтроку("UTF-8");
// Диагностическая проверка — что реально пришло
Если СтрНачинаетсяС(СокрЛП(Ответ), "<") Тогда
ВызватьИсключение "Сервер вернул не JSON: " + Лев(Ответ, 200);
КонецЕсли;
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ);
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
Если у API есть параметр формата (format=json vs format=xml) —
убедитесь, что запрашиваете именно JSON. Проверяйте и заголовок
Accept: application/json — некоторые сервисы по умолчанию отдают XML.
Причина №4: одинарные кавычки и ключи без кавычек
JSON-грамматика допускает только двойные кавычки (") вокруг ключей и строк.
Но многие API и особенно «браузерные» источники возвращают JavaScript-объектный литерал:
ключи без кавычек либо в одинарных кавычках, «умные» кавычки из Word
(«, »). Такой контент 1С не прожуёт.
Минимальная нормализация перед разбором (не серебряная пуля, но снимает 80% случаев):
// Меняем «умные» кавычки (U+00AB «, U+00BB », U+201C “, U+201D ”) на обычные
Ответ = СтрЗаменить(Ответ, Символ(171), """"); // «
Ответ = СтрЗаменить(Ответ, Символ(187), """"); // »
Ответ = СтрЗаменить(Ответ, Символ(8220), """"); // “
Ответ = СтрЗаменить(Ответ, Символ(8221), """"); // ”
// Если абсолютно уверены, что в значениях нет одинарных кавычек:
Ответ = СтрЗаменить(Ответ, "'", """");
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ);
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
Если контент нестандартный систематически — заведите свой парсер на регулярках или
попросите поставщика API вернуть корректный JSON. Массовый СтрЗаменить
ломает данные, где одинарная кавычка — часть значения (апострофы, тексты).
Причина №5: числовые ключи и дефисы в именах — читайте в Соответствие
Отдельный подкласс ошибки, который на форумах часто путают с «непредвиденным символом»:
парсер отработал, но упал на этапе преобразования в структуру с текстом
Недопустимое имя свойства. Причина — второй параметр
ПрочитатьJSON(ЧтениеJSON, ПрочитатьВСоответствие). Если оставить его
Ложь (по умолчанию), 1С пытается положить ключи в структуру,
а имя поля структуры не может начинаться с цифры или содержать дефис
("0", "tem-53", "@id").
// Правильно: читаем в Соответствие, а не в Структуру
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ);
Данные = ПрочитатьJSON(ЧтениеJSON, Истина); // ← ключевой параметр
// Обращение — как к Соответствию
Заказ = Данные["response"]["orders"]["tem-53"];
Сумма = Заказ["amount"];
Причина №6: вложенный JSON-строкой без экранирования
Реальный кейс с infostart: сервис отдаёт поле additional_data, куда «зашит»
ещё один JSON, но кавычки внутри не экранированы. Итоговая строка невалидна:
{
"order_number": "tem-53",
"additional_data": "{"email":"user@mipt.ru","fullName":"ФИО"}"
}
ЧтениеJSON увидит закрывающую " после { и
решит, что значение закончилось, а дальше пойдёт «непредвиденный символ». Правильно
было бы экранировать: "additional_data": "{\"email\":\"user@mipt.ru\"}".
Если API чинить нельзя — вытащите проблемное значение регуляркой до
ПрочитатьJSON и разберите его отдельно:
// Грубая изоляция вложенного объекта по маркеру
ПозицияДопДанных = СтрНайти(Ответ, """additional_data"":");
// … дальше выделяем подстроку от первой { до парной } и парсим её отдельным ЧтениеJSON.
// Более чистый путь — предварительно экранировать кавычки внутри значения:
Ответ = СтрЗаменить(Ответ, ": ""{", ": ""{"); // маркер начала
// … нормализация зависит от конкретного формата API.
Причина №7: управляющие и невидимые символы внутри значений
JSON запрещает «сырые» управляющие символы (табы, переносы строк, возврат каретки)
внутри строковых значений — они должны быть экранированы как \t, \n,
\r. Если сервер вернул многострочный комментарий «как есть», парсер сообщит
«непредвиденный символ» и укажет позицию невидимого байта.
Плюс встречаются «мусорные» коды: Символ(0) (нулевой байт), NBSP
(Символ(160)), zero-width space (Символ(8203)). Их удобно
вычистить одной функцией перед УстановитьСтроку:
Функция ОчиститьСлужебные(Строка)
Результат = Строка;
Для Каждого КодСимвола Из Новый Массив(0, 8203, 65279) Цикл
Результат = СтрЗаменить(Результат, Символ(КодСимвола), "");
КонецЦикла;
Возврат Результат;
КонецФункции
Как найти точную позицию «плохого» символа
Когда причина не очевидна, найдите позицию, на которой падает ПрочитатьJSON —
так быстрее любых догадок. У объекта ЧтениеJSON есть свойства
ТекущаяПозиция и ТекущаяСтрока, которые доступны и в
исключении:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ);
Попытка
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
Исключение
Позиция = ЧтениеJSON.ТекущаяПозиция;
НомерСтр = ЧтениеJSON.ТекущаяСтрока;
Окно = Сред(Ответ, Макс(Позиция - 30, 1), 60);
ЗаписьЖурналаРегистрации(
"JSON.parse",
УровеньЖурналаРегистрации.Ошибка,
,,
"Строка " + НомерСтр + ", позиция " + Позиция + ", контекст: [" + Окно + "]"
);
ВызватьИсключение;
КонецПопытки;
Дополнительный приём для «трудных» ответов — сохранить сырое тело в файл и открыть его
в редакторе с показом невидимых символов (Notepad++, VS Code с плагином Gremlins),
либо прогнать через jsonlint.com — валидатор укажет строку и колонку
ошибки в человеческом виде.
Прямо из чата AI-агент дёрнет ПрочитатьJSON на живой строке,
поймает исключение, покажет ТекущаяПозиция, окно вокруг ошибки
и подскажет, что нормализовать: BOM, кавычки, кодировку или структуру.
Частые ошибки при чтении JSON в 1С 8.3
-
Забыли закрыть
ЧтениеJSON.Закрыть(). Не приводит к «непредвиденному символу», но течёт файловый дескриптор при чтении файлов. -
Игнорируют второй параметр
ПрочитатьJSON. ОставляютЛожь, получают «недопустимое имя свойства» на числовых ключах вроде"0"и"200". СтавьтеИстина, если ключи приходят «как есть» из внешнего API. -
Читают ответ как
ПолучитьТелоКакСтроку()без кодировки. 1С использует системную кодировку сервера — на linux это UTF-8, на Windows-сервере часто cp1251. Всегда указывайте кодировку явно. -
Не отделяют HTTP-ошибки от бизнес-ошибок. Сначала проверяйте
КодСостояния, потомContent-Type, и только потом парсите JSON — иначе получите непредвиденный символ на HTML-странице ошибки. -
Используют JSONP-обёртку
callback({...})как JSON. Обрежьте префикс и последнюю)доУстановитьСтроку. -
Trailing comma в объекте/массиве.
{"a":1,}— невалидный JSON, хотя JavaScript такое принимает. Либо чините источник, либо подчищайте регуляркой перед разбором.
Чек-лист диагностики: 5 шагов от ошибки к рабочему разбору
- 1. Залогируйте первые 200 символов сырого ответа и сравните с ожидаемым JSON.
- 2. Проверьте
КодСостоянияиContent-TypeHTTP-ответа. - 3. Явно укажите кодировку в
ПолучитьТелоКакСтроку("UTF-8"). - 4. Уберите BOM:
СтрЗаменить(Ответ, Символ(65279), ""). - 5. В
ПрочитатьJSONвторым параметром поставьтеИстина— читайте в Соответствие.
Этих пяти шагов достаточно, чтобы закрыть подавляющую часть жалоб на
«прочитатьjson 1с 8.3 непредвиденный символ». Если после этого падение остаётся —
смотрите позицию через ТекущаяПозиция и работайте с конкретным
байтом.
Частые вопросы про «Непредвиденный символ при чтении JSON» в 1С
Как в 1С убрать BOM перед ПрочитатьJSON?
Если данные уже в строке — вызовите СтрЗаменить(Строка, Символ(65279), "")
до УстановитьСтроку. Если читаете файл — используйте
ЧтениеТекста с явной кодировкой "UTF-8" или
ЧтениеJSON.ОткрытьФайл(Путь, "UTF-8"): платформа сама пропустит BOM.
Почему ПрочитатьJSON падает, хотя строка валидна на jsonlint?
Скорее всего вы читаете тело HTTP-ответа в неверной кодировке (например, UTF-8, когда
сервер отдал cp1251). Проверьте заголовок Content-Type и передайте
нужную кодировку в ПолучитьТелоКакСтроку — символы кириллицы перестанут
превращаться в мусор.
Как найти позицию непредвиденного символа при чтении JSON?
Оберните ПрочитатьJSON в Попытка…Исключение и в блоке
исключения прочитайте ЧтениеJSON.ТекущаяПозиция и
ЧтениеJSON.ТекущаяСтрока. Дальше вырежьте окно
Сред(Ответ, Позиция - 30, 60) — этого хватает, чтобы увидеть проблемный
байт в контексте.