Skip to content

Leave computed fields out of Pydantic payloads so extra="forbid" models decode - #2053

Open
sohom-cs wants to merge 1 commit into
temporalio:mainfrom
sohom-cs:fix/pydantic-computed-fields-round-trip
Open

sohom-cs wants to merge 1 commit into
temporalio:mainfrom
sohom-cs:fix/pydantic-computed-fields-round-trip

Conversation

@sohom-cs

Copy link
Copy Markdown

What was changed

PydanticJSONPlainPayloadConverter.to_payload now passes round_trip=True to pydantic_core.to_json (no options) and to SchemaSerializer.to_json (ToJsonOptions set). In that mode pydantic leaves computed fields out and writes Json[...] fields as JSON strings, so from_payload can validate what to_payload wrote. The to_payload docstring says so, and there is a changelog/fixed fragment.

Why?

Computed fields were written to payloads and then read back as input keys: models with extra="forbid" failed with extra_forbidden, and models with extra="allow" decoded with the computed value stored again as an extra. Json[...] fields were written as objects and failed with json_type. Details, and the alternatives I tried, are in #2052.

This changes payload bytes: computed fields are no longer written, and Json[...] fields are strings. Python receivers recompute computed fields on decode; anything reading the payload JSON directly (UI, CLI, other SDKs) no longer sees them. Decoding is unchanged, so payloads already in histories decode as they do today. On pydantic 2.0 to 2.3, round_trip=True still writes computed fields, so there only Json[...] fields change.

Checklist

  1. Closes [Bug] Pydantic converter writes computed fields that models with extra="forbid" then reject #2052

  2. How was this tested:
    New test test_payload_validates_back_to_value in tests/contrib/pydantic/test_pydantic.py, for no options, ToJsonOptions() and ToJsonOptions(exclude_unset=True), with four values: an extra="forbid" model with a computed field, a list of them, an extra="allow" model with a computed field, and a model with a Json[dict[str, int]] field. It checks that the payload decodes to an equal value, then the exact bytes.

  • Without the change: 12 failed (9 ValidationError, 3 unequal values). With it: 12 passed.
  • tests/contrib/pydantic with a local dev server: 51 passed. The keep aliases and inf/nan when ToJsonOptions is set #2039 tests pass unchanged.
  • tests/test_converter.py, tests/test_serialization_context.py, tests/test_plugins.py, and tests/worker/test_workflow.py -k pydantic: 80 passed.
  • poe lint clean.
  • At the pydantic level, on 2.0.3, 2.4.2, 2.10.6, 2.11.0, 2.12.0 and 2.14.1: computed fields are left out from 2.4 on, and Json[...] fields round-trip on all six.
  • Not run: the ai-integrations plugin suites, or other SDKs and the UI reading the new payloads.
  1. Any docs updates needed?
    No. The to_payload docstring and the changelog fragment describe the change.

…ls decode

Serialize with round_trip=True on both the default path and the
ToJsonOptions path, so that from_payload can validate what to_payload
wrote: computed fields are left out (validation recomputes them) and
Json[...] fields are written as JSON strings.
@sohom-cs
sohom-cs requested a review from a team as a code owner October 31, 2026 02:48
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-31T02:49:51.440854Z
We couldn’t complete this review. Comment @codex review to try again.
766c9b7 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Pydantic converter writes computed fields that models with extra="forbid" then reject

1 participant