cloudevents / sdk-python

Python SDK for CloudEvents
https://pypi.org/p/cloudevents/
Apache License 2.0
279 stars 55 forks source link

nested pydantic cloudevent serialization doesn't work #198

Open sasha-tkachev opened 1 year ago

sasha-tkachev commented 1 year ago
CloudEvent(..., data=CloudEvent(...)).json()

will not work

I will fix it myself

xSAVIKx commented 1 year ago

that's kinda the "default" behavior, but sure, let's wait for a PR 👍

hozn commented 9 months ago

I'm having this issue as well, but in pydantic v2. It works fine in vanilla pydantic, but does not work with the CloudEvent -- or subclasses, as I am using.

In my specific case, I have a Generic subclass for our models.

import uuid
from typing import Generic, TypeVar

from cloudevents.pydantic.v2 import CloudEvent
from pydantic import BaseModel

T = TypeVar("T", bound=BaseModel)

class MyEntity(BaseModel):
    id: uuid.UUID

class MyCloudEvent(CloudEvent, Generic[T]):
    data: T

if __name__ == "__main__":
    obj = MyEntity(id=uuid.uuid4())

    evt = MyCloudEvent(
        id=str(uuid.uuid4()),
        source="urn:source",
        subject="subject",
        data=obj,
        event_type="MyEntity",
        type="xyz",
    )
    # This works:
    # print(evt.model_dump(mode="python"))

    # But this does not:
    print(evt.model_dump(mode="json"))

Stack trace snippet:

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/hans/Library/Application Support/JetBrains/PyCharm2023.2/scratches/scratch_42.py", line 30, in <module>
    print(evt.model_dump(mode="json"))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/hans/Library/Caches/pypoetry/virtualenvs/cvPU66vz-py3.11/lib/python3.11/site-packages/pydantic/main.py", line 308, in model_dump
    return self.__pydantic_serializer__.to_python(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.PydanticSerializationError: Error calling function `_ce_json_dumps`: TypeError: Object of type MyEntity is not JSON serializable
hozn commented 9 months ago

We're using fastapi, so the workaround I'm using for the above nested-object serialization issue is:

from fastapi.encoders import jsonable_encoder

jsonable_encoder(event.model_dump(mode="python"))

Which works ... but this used to work without these extra hoops in pydantic v1 (and older cloudevents lib).