Короткий ответ
Совместимые изменения — это добавление новых опциональных полей в ответ и новых опциональных параметров запроса; несовместимые — удаление или переименование существующих полей, изменение их типа/семантики, добавление нового обязательного параметра запроса. Чтобы остаться совместимым, нужно только добавлять, не ломая то, что уже используют клиенты.
Как это работает подробнее
клиенты, написанные по принципу "игнорировать неизвестные поля" (что является хорошей практикой десериализации), не заметят появления нового поля в ответе; но они точно заметят исчезновение поля, на которое опирались, или смену его типа (например, число стало строкой).
Пример кода
example.json
// Было (v1, используется клиентами)
{"id": 42, "total": 150.0}
// Совместимое изменение: добавлено новое опциональное поле
{"id": 42, "total": 150.0, "currency": "USD"}
// Несовместимое изменение: поле удалено/переименовано без алиаса — ломает текущих клиентов
{"id": 42, "amount": 150.0}Что использовать на практике
- Рекомендация. перед изменением контракта стоит явно classifицировать изменение как совместимое/несовместимое, опираясь на контракт (OpenAPI-схему), а не "на глаз"; для потенциально несовместимых изменений — использовать стратегию расширения (добавить новое поле рядом со старым, период параллельной поддержки обоих, затем депрекация старого с предупреждением в документации/заголовке
Deprecation).
Подводные камни
- Риски. переименовывать поле "для ясности" без сохранения старого имени как алиаса хотя бы на переходный период, молча ломая клиентов, которые не следят за changelog; менять тип существующего поля (например,
"id": 123на"id": "123") без версионирования, рассчитывая, что это "мелочь", хотя строго типизированные клиенты (например, сгенерированные из OpenAPI) могут упасть при десериализации.