При разработке интеграций или формировании сложных отчетов в формате JSON часто возникает задача динамического заполнения структур и массивов внутри цикла. Однако начинающие разработчики часто сталкиваются с неприятным эффектом: в итоговом массиве все элементы оказываются одинаковыми (обычно — последним добавленным значением). Давайте разберемся, почему так происходит и как правильно организовать код.
Главная причина кроется в том, как 1С работает с объектами типа Структура или Массив. Когда вы пишете Объект = Новый Структура, вы не просто создаете значение — вы выделяете область в оперативной памяти и присваиваете переменной ссылку на этот объект.
Если вы создаете структуру вне цикла, то внутри итераций вы работаете с одной и той же ссылкой. Каждое изменение ключа (например, Структура.Вставить("stocks", ...)) фактически меняет содержимое одного и того же объекта в памяти. В результате, когда цикл завершается, все элементы, которые вы «добавляли» в массив, на самом деле указывают на один и тот же объект, который хранит последнее записанное значение.
Рассмотрим классический пример ошибочного кода, который приводит к затиранию данных:
// ОШИБОЧНЫЙ ПОДХОД
СтруктураДанныхJSON = Новый Структура; // Создали вне цикла
Для ч = 1 По 4 Цикл
тДанные = Новый Структура;
тДанные.Вставить("chrtId", ч);
МассивStoks = Новый Массив;
МассивStoks.Добавить(тДанные);
// Ссылка одна и та же, перезаписываем старые данные
СтруктураДанныхJSON.Вставить("stocks", МассивStoks);
МассивДанныхJSON.Добавить(СтруктураДанныхJSON);
КонецЦикла;
В этом примере каждый элемент в МассивДанныхJSON ссылается на одну и ту же переменную СтруктураДанныхJSON. При каждой итерации вы обновляете её содержимое, и во всех ссылках внутри массива «вдруг» оказывается последнее значение. Это происходит потому, что массив хранит не копию структуры, а адрес в памяти.
Чтобы избежать такой ситуации, необходимо следовать золотому правилу: каждая итерация — новый объект. Инициализацию любой коллекции (структуры, массива), которую вы планируете добавлять в другой массив, нужно перенести внутрь тела цикла.
Давайте посмотрим на исправленный код:
// ПРАВИЛЬНЫЙ ПОДХОД
МассивДанныхJSON = Новый Массив;
Для ч = 1 По 4 Цикл
// Создаем новую структуру на каждой итерации
СтруктураДанныхJSON = Новый Структура;
МассивStoks = Новый Массив;
тДанные = Новый Структура;
тДанные.Вставить("chrtId", ч);
МассивStoks.Добавить(тДанные);
СтруктураДанныхJSON.Вставить("stocks", МассивStoks);
// Теперь в массив добавляется уникальный объект, созданный в этой итерации
МассивДанныхJSON.Добавить(СтруктураДанныхJSON);
КонецЦикла;
Для...По сам инкрементирует счетчик. Использование конструкции типа ч = ч + 1 внутри тела цикла приведет к пропускам элементов, так как цикл будет увеличивать счетчик дважды за одну итерацию.ЗаписатьJSON не делает «фотографию» данных в момент добавления. Если вы передадите ссылку на объект, который меняется позже, в JSON попадет именно то состояние, которое объект имел на момент сериализации. Поэтому создание объектов внутри цикла критически важно для целостности данных.Используя этот подход, вы гарантируете, что каждый элемент вашего массива будет уникальным объектом, изолированным от других в оперативной памяти. Это исключит ошибки перезаписи и обеспечит корректную структуру вашего JSON-файла.