Почему при заполнении массива в цикле 1С данные затираются и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интеграций или формировании сложных отчетов в формате 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);
КонецЦикла;

Важные советы по работе с циклами и JSON

  1. Не используйте ручное управление итератором: В 1С цикл Для...По сам инкрементирует счетчик. Использование конструкции типа ч = ч + 1 внутри тела цикла приведет к пропускам элементов, так как цикл будет увеличивать счетчик дважды за одну итерацию.
  2. Сериализация: Метод ЗаписатьJSON не делает «фотографию» данных в момент добавления. Если вы передадите ссылку на объект, который меняется позже, в JSON попадет именно то состояние, которое объект имел на момент сериализации. Поэтому создание объектов внутри цикла критически важно для целостности данных.
  3. Структура данных: Всегда четко разделяйте уровни вложенности. Если ваша JSON-структура многоуровневая (как в вашем примере: массив внутри структуры, внутри другого массива), убедитесь, что на каждом уровне вложенности новые коллекции создаются именно внутри того цикла, в котором они должны наполняться.

Используя этот подход, вы гарантируете, что каждый элемент вашего массива будет уникальным объектом, изолированным от других в оперативной памяти. Это исключит ошибки перезаписи и обеспечит корректную структуру вашего JSON-файла.

← На главную