Имя поля не изменилось, но изменилось значение, а нижестоящий тихонько допустил ошибку: добавьте номер версии в результат извлечения

На прошлой неделе `amount` представлял собой "центы", но на этой неделе он был изменен на "юани", но имя поля не изменилось. Проверка типа по-прежнему проходит, но результаты бизнеса могут оказаться на два порядка хуже. Наиболее опасным обновлением интерфейса извлечения часто является не явное сообщение об ошибке, а незаметное изменение смысла.

— Номер версии должен соответствовать независимым валидаторам и функциям миграции, иначе это просто декоративное поле. — Функция миграции применяет тип (центы) — int, чтобы исключить логические значения, чтобы True не рассматривалось как копейки.

  • Старые записи с неопределенными единицами измерения не должны преобразовываться предположительно и должны явно давать сбой и сохранять исходные данные.
  • В записи миграции необходимо сохранить входную и выходную версию, версию программы миграции, идентификатор исходной записи и причину сбоя.

Эта статья написана для разработчиков и последующих групп данных, которые поддерживают интерфейсы извлечения документов. После обновления результатов извлечения имена полей могут не измениться, но их значение будет другим. Например, если amount изменить с «фэнь» на «юань», проверка типа все равно пройдет, но бизнес-номера могут отличаться на два порядка.

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

В примерах этой статьи используются синтетические образцы, а код проверен на примерах в изолированной среде. Это не является гарантией всех реальных файлов или эффектов продукта. Перед обработкой важных документов, пожалуйста, сохраните оригиналы и просмотрите их по границам и пунктам приема в тексте.

Имя поля не изменилось, но изменилось его значение. Как с этим справиться? Вывод в одно предложение

Пометьте каждый вывод с помощью schema_version и используйте явные функции миграции для преобразования различных версий данных вместо того, чтобы просто помечать новую версию.

твоя ситуацияРекомендуемые практикипричина
Просто добавьте поляДобавьте новое поле и запишите версиюДобавление полей — это не то же самое, что изменение единиц измерения.
Изменение единиц поля или семантикиВыбор валидаторов и функций миграции по версииЗначение одноименных полей незаметно изменится
Старые записи имеют неопределенные единицы измеренияВыяснить ошибку, сохранить старые данные и добавить доказательстваФункции миграции не должны быть догадками
Нисходящий поток поглотил старый интерфейсЗапланировать смену версииНельзя ожидать, что нисходящий поток автоматически обнаружит числовые семантические изменения.
Проверьте перевод с результатами извлеченияСохранять информацию о версии протокола для сгенерированных полей.Удобно проверить «чем этот раз отличается от прошлого»

Номер версии должен соответствовать семантике

Добавление поля — это не то же самое, что изменение единиц измерения. Вы можете предоставить каждому выходу schema_version и выбрать валидаторы и функции миграции по версии.

Номера версий сами по себе не защищают систему. Если все версии следуют одной и той же недифференцированной логике синтаксического анализа, это просто декоративное поле.

Ключ к версионному анализу

  • Выбор правил синтаксического анализа по версии: разные версии используют свои собственные валидаторы.
  • Миграция — это явное преобразование данных: речь не идет о непосредственном присвоении старым данным новой версии.
  • Семантические изменения должны быть прослеживаемы: должна быть возможность просматривать такие правила, как единицы измерения и точность.

В следующем примере показано, как преобразовать целое число баллов в строку десятичной суммы.

Функция проверяемой миграции

from decimal import Decimal

def migrate(record):
    if record.get("schema_version") != "v1":
        raise ValueError("unexpected input version")
    cents = record.get("amount_cents")
    if type(cents) is not int:
        raise ValueError("integer cents required")
    return {"schema_version": "v2",
            "amount": format(Decimal(cents) / Decimal(100), ".2f"),
            "currency": record["currency"]}

old = {"schema_version": "v1", "amount_cents": 12345, "currency": "USD"}
new = migrate(old)
assert new["amount"] == "123.45"
assert old["amount_cents"] == 12345
assert migrate({**old, "amount_cents": -25})["amount"] == "-0.25"
try:
    migrate({**old, "amount_cents": True})
except ValueError:
    pass
else:
    raise AssertionError("bool is not a monetary integer here")

В этом примере предполагается, что входная валюта использует процентное отношение, а выходные данные имеют два десятичных знака. Это не универсальный конвертер, охватывающий все денежные единицы.

type(cents) is int намеренно исключает логические значения как целочисленные подклассы в Python, чтобы не принимать True за копейки.

📊 Сравнение ядра: только номер версии и версионная миграция

упражнятьсяЭффектограничения
Добавляйте только поле schema_versionВывод помечен версиейЕсли все версии по-прежнему следуют одной и той же логике синтаксического анализа, номер версии является просто украшением.
Выбор валидаторов и функций миграции по версииПоля с одинаковыми именами имеют понятные пояснения в разных версиях.Необходимо прописать правила конвертации для каждой версии

Что следует оставить в записи миграции?

Во время миграции рекомендуется записать следующую информацию, чтобы облегчить возврат и обработку разгрузки.

информацияиспользоватьриск пропустить
Версии ввода и выводаВыберите правильное правило интерпретацииЗначение полей с одинаковыми именами сбивает с толку.
Версия программы миграцииВоспроизведение результатов преобразованияНеобъяснимые результаты после обновления
Оригинальная идентификационная записьПолучить источникНовые и старые данные не могут соответствовать
Причина неудачиРучная обработка перенаправленияНеквалифицированные данные заполняются значениями по умолчанию.

Не быть бесконечно совместимым с историческими ошибками

Если единицы старой записи сами по себе неопределенны, функция миграции не должна предполагать. Более подходящий подход — вернуть явный отказ, сохранить старые данные и запросить дополнительные доказательства.

Для последующих пользователей, которые уже используют старый интерфейс, также следует организовать переключение версий, а не ожидать, что он автоматически обнаружит, что семантика значений изменилась.

Источники: Общие ключевые слова JSON Schema

Проверка после перевода также требует знания версии

При использовании извлеченных полей для проверки переводов OmniDoc (портал продуктов) необходимо указать, по какому протоколу были сгенерированы поля. Изменения в исходных файлах, правилах извлечения или целевом языке могут повлиять на метод сравнения.

Сохранение информации о версии может сделать вопрос «почему этот раз отличается от прошлого» проблемой, которую можно устранить, вместо того, чтобы просто приписывать ее нестабильности модели.

🎯 Какой метод подходит вам?

Если вы просто добавите новое поле

Добавьте новое поле напрямую и запишите schema_version в выходных данных.

Если вы хотите изменить единицу измерения или значение поля

Напишите независимые валидаторы и функции миграции для новой версии и не используйте повторно старую логику синтаксического анализа.

Если ваша единица исторических данных не ясна

Дайте понять, что миграция не удалась, сохраните исходные данные и добавьте доказательства перед обработкой.

❓ Часто задаваемые вопросы (FAQ)

1. Достаточно ли просто добавить в вывод номер версии?

недостаточно. Номер версии — это просто метка, и он не может защитить бизнес-значение, если все версии по-прежнему используют одну и ту же логику синтаксического анализа.

2. Почему функция миграции исключает логические значения?

Логические значения в Python являются подклассом целых чисел, и type(cents) is int не позволяет True приниматься за копейки.

3. Что делать, если старый блок записи ненадежен?

Функции миграции не должны строиться наугад. Следует вернуть явный отказ, сохранить старые данные и запросить дополнительные доказательства.

4. Какую информацию необходимо сохранять в миграционных записях?

Как минимум, укажите версии ввода и вывода, версию программы миграции, исходную идентификацию записи и причину сбоя.

📝 Резюме

Тот факт, что имя поля остается неизменным, не означает, что значение остается неизменным. Управление версиями выходных данных и обработка семантических изменений с помощью явных функций миграции и записей миграции могут значительно снизить риск скрытых ошибок в дальнейшем.

Попробуйте сейчас: загрузите документ, чтобы начать перевод, сохранив исходный макет.

Обновлено 2026-11-15