marshmallow-code / marshmallow-sqlalchemy

SQLAlchemy integration with marshmallow
https://marshmallow-sqlalchemy.readthedocs.io
MIT License
549 stars 94 forks source link

ARRAY column doesn't map correctly #537

Closed jsormaz closed 10 months ago

jsormaz commented 10 months ago

I have an array column defined as follows:

from sqlalchemy import ARRAY, DateTime
...
class HistoryTable(Base):
    timestamps = Column(ARRAY(DateTime(timezone=True)), default=[])
...

However, when I dump this object, this column gets mapped to <class 'marshmallow.fields.Raw'>

in marshmallows_sqlalchemy/convert.py, we have:

    """Class that converts a SQLAlchemy model into a dictionary of corresponding
    marshmallow `Fields <marshmallow.fields.Field>`.
    """

    SQLA_TYPE_MAPPING = {
       ...
        postgresql.ARRAY: _postgres_array_factory,
        ...
    }

however, when I inspect my column, the mro is presenting as:

(
<class 'sqlalchemy.sql.sqltypes.ARRAY'>, 
<class 'sqlalchemy.sql.base.SchemaEventTarget'>, 
<class 'sqlalchemy.event.registry.EventTarget'>, 
<class 'sqlalchemy.sql.sqltypes.Indexable'>, 
<class 'sqlalchemy.sql.sqltypes.Concatenable'>, 
<class 'sqlalchemy.sql.type_api.TypeEngineMixin'>, 
<class 'sqlalchemy.sql.type_api.TypeEngine'>, 
<class 'sqlalchemy.sql.visitors.Visitable'>, 
<class 'typing.Generic'>, 
<class 'object'>
)

so it is not matching against the "postgressql.ARRAY" key

jsormaz commented 10 months ago

Seems that I can just force the behaviour I want by initializing my column from the postgressql ARRAY type directly:'

from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy import DateTime
...
class HistoryTable(Base):
    timestamps = Column(ARRAY(DateTime(timezone=True)), default=[])
...