I'm looking for a way to have a pydantic object stored in a sqlalchemy json column. My attempts so far are being tripped up by a datetime field in the pydantic object. I feel like I'm missing something obvious.
My first attempt was to simply serialise the result of .dict(). But this doesn't convert datetime objects to strings so the serialiser falls over. If I convert with .json then the result is a string and what's stored in the database is the json of a string not a dict.
import sqlalchemy.orm
from pydantic import BaseModel
from datetime import datetime
mapper_registry = sqlalchemy.orm.registry()
Base = mapper_registry.generate_base()
class _PydanticType(sqlalchemy.types.TypeDecorator):
impl = sqlalchemy.types.JSON
def __init__(self, pydantic_type):
super().__init__()
self._pydantic_type = pydantic_type
def process_bind_param(self, value, dialect):
return value.dict() if value else None
def process_result_value(self, value, dialect):
return self._pydantic_type.parse_obj(value) if value else None
class Test(BaseModel):
timestamp: datetime
class Foo(Base):
__tablename__ = 'foo'
x = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
y = sqlalchemy.Column(_PydanticType(Test))
engine = sqlalchemy.create_engine('sqlite:///x.db', echo=True)
mapper_registry.metadata.create_all(bind=engine)
session = sqlalchemy.orm.sessionmaker(bind=engine)()
session.add(Foo(x=1, y=Test(timestamp=datetime.now())))
session.commit()
sqlalchemy.exc.StatementError: (builtins.TypeError) Object of type datetime is not JSON serializable