Empty Field in the API: When to Save a Value and When to Clear It
A missing property, null, an empty string, and zero can all signify different changes. We examine the partial update contract using an online store exchange example.

In this article
Представим обмен заказами: в заказе был комментарий «Позвонить за час до доставки». После обмена с учётной системой поле стало пустым, хотя покупатель ничего не удалял. В журнале нет ошибки: отправитель передал пустое значение, получатель честно его сохранил. Сбой произошёл раньше — когда два разных намерения превратились в одинаковый пакет данных.
Для частичного обновления нужно отдельно договориться о трёх действиях: оставить прежнее значение, установить новое и очистить поле. Сам JSON такого соглашения не даёт. Отсутствующее свойство, null, пустая строка и ноль различаются в данных; смысл изменения задаёт контракт конкретного метода. Это особенно полезно проверить в обмене магазина на 1С-Битрикс с 1С, CRM или собственной службой доставки.
Одно поле, три разных просьбы
Возьмём условный заказ с полем comment. Клиент меняет только адрес доставки. Если он вообще не передал comment, это может означать «комментарий не трогать». Если покупатель стёр текст, интеграция должна передать отдельное, однозначное намерение очистить комментарий. Превращать оба случая в пустую строку на этапе выгрузки нельзя: восстановить исходное намерение по такому сообщению уже не получится.
Здесь важна граница применимости. В одном API отсутствие поля означает сохранение старого значения, в другом метод принимает полное состояние объекта и требует обязательные поля. Само слово «обновить» в названии метода ничего не гарантирует. Сначала выясняем, передаём ли мы изменения или новую полную версию данных; затем выбираем представление пустоты.
Есть стандартный вариант частичных изменений — JSON Merge Patch, описанный в RFC 7396. В объекте такого патча отсутствующее свойство остаётся без изменения, скалярное значение или массив заменяет прежнее, а null означает удаление свойства. Вложенные объекты обрабатываются рекурсивно по тем же правилам. Это правило именно данного формата, а не универсальная трактовка любого JSON-запроса.
Пусть исходный объект содержит {"comment":"Позвонить за час до доставки","quantity":2}. Патч {"quantity":0} меняет количество на ноль и сохраняет комментарий. Патч {"comment":null} удаляет свойство комментария. Патч {"comment":""} оставляет свойство с пустой строкой. Последние два результата могут выглядеть одинаково в форме заказа, но для следующего обработчика они различны.
Если предметной модели нужно хранить null как самостоятельное значение, такая семантика удаления неудобна. Нельзя одновременно договориться, что одно и то же действие означает и «сохранить неизвестное значение», и «удалить свойство». Придётся выбрать другое представление операции или другой формат изменений и описать его явно.

Ноль нельзя потерять по дороге
Условие «если значение непустое, отправить поле» выглядит компактно. Однако такая проверка ошибочно исключает допустимые данные из отправки. Количество товара, равное нулю, бесплатная доставка и отключённый признак могут быть вполне содержательными значениями.
Например, по условному контракту количество разрешено менять на ноль. Проверять нужно наличие свойства и допустимость его значения, а не общую «истинность» значения в языке программирования. Если отправитель исключит ноль из пакета, получатель частичного обновления сохранит прежние две единицы. Корректный JSON в этом случае доставит неверное количество товара.
Отдельно проверяют промежуточные преобразования: выгрузку из 1С, модель модуля обмена, очередь и клиент внешнего API. Один компонент может отличать отсутствующее свойство от null, а следующий — заменять оба случая значением по умолчанию. Поэтому полезно сопоставить обезличенный исходный пакет с пакетом непосредственно перед отправкой, не ограничиваясь полями в интерфейсе магазина.
Пустой массив — ещё один договор
Список телефонов или вложений добавляет новый вопрос: передаются отдельные изменения элементов или весь список? В JSON Merge Patch массив заменяется целиком. Пустой массив [] заменит старый массив пустым; передача одного элемента не означает «добавить только его к остальным».
В собственном методе интеграции правила могут отличаться. Но название поля не объяснит, означает ли пустой список очистку, отсутствие доступных сведений или ошибку формирования выгрузки. Особенно неприятен случай, когда отправитель не смог получить вложения и подставил пустой массив: техническая неудача превращается в команду удаления связей.
Если сведения получить не удалось, лучше вернуть наблюдаемую ошибку этой операции или отложить изменение соответствующего поля по согласованному правилу. Нельзя выдавать неизвестное состояние за подтверждённую пустоту. И нельзя молча пропускать поле, если контракт требует полной версии объекта: тогда пакет следует отклонить до применения.
Что проверить на копии интеграции
Для одного выбранного поля заранее фиксируют исходное состояние и ожидаемый результат. Затем проверяют отдельные случаи:
поле отсутствует в запросе;
передан
null;передана пустая строка;
передан ноль или
false, если тип поля это допускает;передан пустой массив, если поле содержит список;
передан неверный тип, например строка вместо ожидаемого числа.
Проверка должна увидеть не только ответ метода, но и сохранённое состояние. Осталось ли свойство в объекте? Сохранилось ли старое значение? Удалились ли связи списка? Не заменил ли следующий этап ноль значением по умолчанию? Такой набор выполняют на тестовой копии с условными данными. Приведённые здесь объекты — учебные примеры; работа конкретного модуля 1С-Битрикс ими не подтверждена.
Для каждого поля получается небольшое правило: что означает отсутствие, чем выражается очистка, какие значения допустимы и кто вправе их менять. Его согласуют между отправителем и получателем до настройки преобразований. Тогда пустой комментарий остаётся осознанным действием пользователя, а не побочным результатом того, что очередная система решила услужливо заполнить пропуск.
Consider an order exchange: the order contained the comment "Call one hour before delivery." After syncing with the accounting system, the field became empty, even though the buyer deleted nothing. The log shows no error: the sender transmitted an empty value, and the receiver faithfully saved it. The failure occurred earlier, when two distinct intents were converted into the same data packet.
For a partial update, you must separately agree on three actions: keep the original value, set a new value, and clear the field. Standard JSON does not provide such an agreement. A missing property, null, an empty string, and zero are distinct in data; the meaning of the change is defined by the contract of the specific method. This is especially useful to verify when exchanging data between a 1C-Bitrix store and 1C, a CRM, or a custom delivery service.
One field, three different requests
Take a hypothetical order with the field comment. The customer changes only the delivery address. If they do not transmit comment at all, this may mean "do not touch the comment." If the buyer deletes the text, the integration must transmit a separate, unambiguous intent to clear the comment. Converting both cases into an empty string during export is not allowed: it becomes impossible to restore the original intent from such a message.
The boundary of applicability is crucial here. In one API, the absence of a field means the old value is preserved, while in another, the method accepts the complete object state and requires mandatory fields. The word "update" in a method name guarantees nothing. First, we determine whether we are sending changes or a new full version of the data; then we choose the representation of emptiness.
There is a standard approach for partial updates: JSON Merge Patch, described in RFC 7396. In such a patch object, a missing property remains unchanged, a scalar value or array replaces the previous one, and null signifies property deletion. Nested objects are processed recursively using the same rules. This rule applies specifically to this format, not as a universal interpretation of any JSON request.
Suppose the original object contains {"comment":"Позвонить за час до доставки","quantity":2}. The patch {"quantity":0} sets the quantity to zero and preserves the comment. The patch {"comment":null} deletes the comment property. The patch {"comment":""} leaves the property with an empty string. The last two results may appear identical in an order form, but for the next handler, they are distinct.
If the domain model needs to store null as a distinct value, this deletion semantics is inconvenient. It is impossible to agree that the same action means both 'save an unknown value' and 'delete the property.' You must choose a different representation for the operation or a different change format and describe it explicitly.

Do not lose zero along the way
The condition 'if the value is not empty, send the field' looks compact. However, such a check erroneously excludes valid data from being sent. A quantity of zero, free shipping, and a disabled flag can all be meaningful values.
For example, under a conditional contract, the quantity is allowed to change to zero. You must check for the presence of the property and the validity of its value, not the general 'truthiness' of the value in the programming language. If the sender excludes zero from the payload, the receiver of a partial update will retain the original two units. In this case, correct JSON delivery results in an incorrect product quantity.
Intermediate transformations are checked separately: export from 1C, the exchange module model, the queue, and the external API client. One component may distinguish a missing property from null, while the next replaces both cases with a default value. Therefore, it is useful to compare the anonymized source package with the package immediately before sending, without limiting the check to fields in the store interface.
An empty array is another agreement
A list of phone numbers or attachments raises a new question: are individual element changes transmitted, or the entire list? In JSON Merge Patch, an array is replaced entirely. An empty array [] replaces the old array with an empty one; transmitting a single element does not mean 'add only this element to the rest.'
In a custom integration method, the rules may differ. However, the field name will not explain whether an empty list means clearing, lack of available information, or an export generation error. The most unpleasant case occurs when the sender cannot retrieve attachments and substitutes an empty array: a technical failure turns into a command to delete relationships.
If the information cannot be obtained, it is better to return the observed error for this operation or defer the field update according to an agreed rule. Do not treat an unknown state as confirmed emptiness. Nor should a field be silently skipped if the contract requires the full object version: in that case, the package must be rejected before application.
What to check on an integration copy
For a single selected field, the initial state and expected result are fixed in advance. Then, individual cases are checked:
the field is missing from the request;
nullis passed;an empty string is passed;
zero or
falseis passed, if the field type allows it;an empty array is passed, if the field contains a list;
an incorrect type is passed, for example, a string instead of the expected number.
The check must verify not only the method's response but also the persisted state. Did the property remain in the object? Was the previous value preserved? Were list relationships removed? Did the next stage replace the value with a default zero? Such a set is executed on a test copy with conditional data. The objects presented here are educational examples; they do not confirm the behavior of a specific 1C-Bitrix module.
For each field, a concise rule is derived: what absence signifies, how clearing is expressed, which values are permissible, and who is authorized to modify them. This rule is agreed upon between the sender and receiver before transformation configuration. Only then does an empty comment represent a deliberate user action rather than an unintended side effect of another system attempting to fill the gap.




Discussion 0
Share your experience and ask questions. Comments without links appear after editorial review.
No comments yet. Start the discussion.