В данной статье сделаем разбор задачи по загрузке файла JSON в 1С, в справочник Номенклатура, с табличной частью. Подобного рода задачи могут попадаться на собеседованиях, в качестве тестовых заданий, либо в качестве практических задач для самостоятельной подготовки. По секрету скажу, что настоящие «боевые» JSON файлы, и соответственно, задачи — бывают куда сложнее.
Условия задачи
- Сделать обработку по заполнению справочника Номенклатура из файла JSON.
- Файл должен выбираться через диалог выбора файла.
- Сопоставление товара по артикулу, предусмотреть повторную загрузку, исключить возможность создания дублей.
- Для новых товаров — заполняем все данные, для найденных уже существующих — только обновляем описание.
- Проверку наличия номенклатуры в базе необходимо производить запросом.
- Проверку изменения описания номенклатуры (в файле поле «description») производить также запросом.
{
"ART-123.X": {
"name": "Беспроводные наушники Pro",
"brand": "SoundTech",
"description": "Высококачественный звук с активным шумоподавлением и до 30 часов работы.",
"components": [
{
"id": "CMP-01",
"partName": "Аккумулятор",
"quantity": 1
},
{
"id": "SPK-L-02",
"partName": "Динамик левый",
"quantity": 2
}
]
},
"SKU_456.B": {
"name": "Механическая клавиатура",
"brand": "KeyMaster",
"description": "RGB подсветка, переключатели Blue, алюминиевый корпус."
},
"MDL.789-A": {
"name": "Умные часы FitBand",
"brand": "WearTech",
"description": "Мониторинг пульса, GPS, водозащита IP68.",
"components": [
{
"id": "BATT-99",
"partName": "Зарядный модуль",
"quantity": 1
}
]
}Обзор решения
Не будем тут подробно останавливаться на том, как сделать обработку, добавить кнопку, прочитать файл через ПоместитьФайлНаСерверАсинх с диалогом выбора файла. Наша основная цель — проанализировать JSON и понять, как его правильно читать и обрабатывать.
Неявные моменты
Внимательно посмотрим на структуру JSON файла. Мы видим, что это не обычный массив, а словарь — т.е. корневой объект, свойства которого — в свою очередь тоже объекты.
Теперь к ключам самих свойств. Во первых, можно сделать предположение, что значения этих свойств и являются артикулами. Во-вторых, как видим, на примере «ART-123.X» — артикулы могут содержать спец. символы, а следовательно, прочитать в структуру мы их не сможем. Делаем себе пометку, что читать будем в соответствие.
Еще один подводный камень — поле «description», по-русски — «описание». Судя по тому, что там достаточно длинные строки, и в условии задачи их длина не ограничена, будем считать, что это поле может содержать строки произвольной длины. А раз так, то в запросе мы не сможем их явным образом сравнить с данными базы, и придется что-то изобретать.
Ошибка, которую часто допускают при сопоставлении данных базы с JSON
Достаточно часто встречаются решения, что называется, «в лоб» — прочитали JSON, получили коллекцию объектов, и начинаем ее перебирать. Каждый объект запросом ищем в базе по ключевым полям — в нашем случае, по артикулу. Потом при необходимости создаем объект, заполняем ему таб. часть, и записываем. А если элемент найден, дополнительно надо сравнить описание, и если описания не совпадают — обновить и так же записать. Схематично такое решение изображено на рисунке ниже. И тут мы получим что? Получим мы — запрос в цикле, что крайне не эффективно с точки зрения производительности, т.к. мы выполним этот запрос столько раз, сколько объектов в нашей коллекции. А если их тысяча? Сто тысяч? Миллион? На масштабе становится понятна неоптимальность такого подхода.
Как оптимизировать решение?
В идеале, мы бы хотели выполнить все за один запрос к базе данных, за один заход сопоставив номенклатуру по артикулам, откинув лишние элементы и оставив только те которые надо создать или обновить.
Но для такого решения ни соответствие, ни структура, ни массив не подойдут — их в запрос не запихнуть. Значит, надо каким-то образом перегнать данные в таблицу значений. При этом, табличные части components нас до поры не интересуют — их можно сложить в отдельное соответствие с ключами по артикулам, а потом по ключам быстро найти нужную таблицу — только для тех элементов Номенклатуры, которые будем создавать.
Важный нюанс! Таблица значений должна быть с типизированными колонками, чтобы запросом можно было ее прочитать.
А что же делать со сравнением поля description?
А тут можно использовать «секретный ингридиент» в виде хеширования. Будем использовать объект ХешированиеДанных, и в принципе, почти любую функцию хеширования, например md5. Там, конечно есть нюансы — в зависимости от функции хеширования, хеш-сумма будет либо двоичными данными, либо числом. Двоичные данные прекрасно можно превратить в строку, и записать в базу данных при создании номенклатуры. а при обновлении — вычислить хеш входящего поля description, дополнить этим хешем нашу промежуточную таблицу значений, и уже в запросе можно будет прекрасно делать сравнение на неравенство.
Заключение
За счет использования промежуточной таблицы значений мы можем избавиться от запроса в цикле и одним запросом сопоставить номенклатуру по артикулу. А за счет использования хеширования поля «description» мы можем сколь угодно большую строку преобразовать к компактной хеш-сумме, и также в том же запросе сравнить с данными в базе.
Это позволит нам многократно уменьшить количество обрабатываемых объектов — оставим только новые или те, где описание не совпадает.
Для самых терпеливых молодцов
Ну и раз уж вы добрались до конца статьи, и хотели бы узнать полное решение с примером, который можно скачать и поковырять в конфигураторе.
Полное видео с решением данной задачи, а также файл конфигурации с примером и файл JSON для загрузки есть в моем закрытом Клубе для разработчиков. Буду рад видеть вас в числе резидентов Клуба!