cloudevents / sdk-python

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

`.json()` unable to serialize datetime elements in `data` payload #213

Open mrossi-kmx opened 1 year ago

mrossi-kmx commented 1 year ago

Expected Behavior

The CloudEvent model, like Pydantic's BaseModel, can serialize of datetime properties to strings in the .json() function.

Actual Behavior

The CloudEvent model raises a ValueError from the standard library's json.dumps function when .json() is called on a model containing datetime properties in the data field.

Alternatively, if this is intentional behavior, it would be helpful to have some guidance around what the expected usage is when users want to have dates or timestamps in their CloudEvent data.

Steps to Reproduce the Problem

  1. Init a CloudEvent where some element of the data argument is a datetime instance.
  2. Call .json() on the CloudEvent instance

For example:

from datetime import datetime

from cloudevents.pydantic import CloudEvent

event = CloudEvent(attributes={'source': 'my.source', 'type': 'com.my.type'}, data={'dt': datetime.now()})

# raises TypeError
print(event.json())

By contrast, Pydantic's BaseModel is able to encode datetime properties:

from datetime import datetime

from pydantic import BaseModel

class MyModel(BaseModel):
  dt: datetime

foo = MyModel(dt=datetime.now())

# encodes dt as a string
print(foo.json())

Specifications

xSAVIKx commented 1 year ago

Hey @mrossi-kmx,

Thx for opening the issue. And yes, currently JSON behavior is not configurable. The Pydantic model is able to perform the conversion while it uses a separate JSON serialization approach.

This should be improved all over the SDK as I mentioned here.

mrossi-kmx commented 1 year ago

Thanks for your response @xSAVIKx! Do you/others have a recommendation for what to do with datetimes in the meantime? Just encode them as strings?

xSAVIKx commented 1 year ago

Thanks for your response @xSAVIKx! Do you/others have a recommendation for what to do with datetimes in the meantime? Just encode them as strings?

That's probably the best approach here. Or you can use Pydantic wrapper if that's ok