Dev-iL commented on PR #61532:
URL: https://github.com/apache/airflow/pull/61532#issuecomment-3875768634

   @jason810496 Please see below Claude's analysis of the point you raised. I 
am going to add the extra test. Please let me know if you think this is 
insufficient.
   
   ------------
   
   ## Reviewer concern: `field_serializer` for UUID fields
   
   The reviewer suggests adding `field_serializer` to UUID fields in Pydantic 
response models to keep responses compatible with `airflow-client-python` 
(which is generated from the OpenAPI YAML spec).
   
   **Is the concern justified?** Partially — there IS an observable schema 
change, but the suggested fix doesn't address it:
   
   1. **JSON wire format (NOT affected):** Pydantic v2 already serializes 
`UUID` objects to dashed strings (`"019c39c7-..."`) by default. A 
`field_serializer` returning `str(id_value)` is redundant — it does exactly 
what Pydantic already does.
   
   2. **OpenAPI schema (IS affected):** Changing `id: str` → `id: UUID` causes 
the generated YAML spec to add `format: uuid`:
      ```yaml
      # Before (str)         # After (UUID)
      id:                     id:
        type: string            type: string
        title: Id               format: uuid   # ← NEW
                                 title: Id
      ```
      This is already reflected in both `v2-rest-api-generated.yaml` (line 
12585) and `_private_ui.yaml` (line 2548).
   
   3. **`field_serializer` does NOT fix the schema:** In Pydantic v2, 
`@field_serializer` only affects **runtime** serialization, not JSON schema 
generation. The schema is derived from the type annotation (`UUID`), so 
`format: uuid` appears regardless of any serializer. To suppress `format: uuid` 
in the schema, you'd need `Annotated[UUID, PlainSerializer(str, 
return_type=str)]` or similar — a fundamentally different approach.
   
   4. **Precedent already exists:** `DagVersionResponse.id` was already `UUID` 
typed and already had `format: uuid` in the OpenAPI spec **before this PR**. 
The pattern is established.
   
   5. **`format: uuid` is non-breaking for clients:** OpenAPI's `format` is a 
hint. The base type is still `string`. Well-behaved client generators treat 
`format: uuid` as validation/documentation, not as a different wire type.
   
   ### Recommendation: Add a serialization regression test (no 
`field_serializer`)
   
   The `field_serializer` is unnecessary since Pydantic already handles the 
conversion. However, a **unit test** documenting the expected serialization 
behavior IS valuable as a regression guard — it protects against future 
Pydantic upgrades or config changes accidentally breaking UUID→string 
serialization.
   
   **Test to add** in a new or existing test file (e.g., 
`airflow-core/tests/unit/api_fastapi/core_api/datamodels/test_task_instances.py`):
   
   ```python
   from uuid import UUID
   from airflow.api_fastapi.core_api.datamodels.task_instances import 
TaskInstanceResponse
   
   def test_uuid_serialized_as_dashed_string():
       """Ensure UUID fields serialize to dashed string format in JSON 
responses.
   
       This guards against regressions that could break airflow-client-python
       and other consumers of the Public API.
       See: https://github.com/apache/airflow/pull/XXXXX
       """
       test_uuid = UUID("019c39c7-4fea-76b6-891d-ebb3267d427d")
       # TaskInstanceResponse requires many fields; construct minimally via 
model_construct
       response = TaskInstanceResponse.model_construct(id=test_uuid)
       json_data = response.model_dump(mode="json")
       assert json_data["id"] == "019c39c7-4fea-76b6-891d-ebb3267d427d"
       assert isinstance(json_data["id"], str)
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to