I want to set the default value of my SQLAlchemy postgres JSON column to an empty dictionary.
from sqlalchemy.dialects.postgresql import JSON
info = Column(JSON, default='{}')
info = Column(JSON, default={})
Neither of these work.
Using default=lambda: {} works. Credit goes to univerio in the comments.
default=dict which is functionally equivalent to the lambda. This still works for me using SQLAlchemy 1.3.xserver_default thoughThe easiest way I've found to define a JSON not null (if applies) column with a default {} value is (tested with SQLAlchemy 1.3.x):
info = db.Column(JSON, nullable=False, server_default='{}')
default, used only server_default='{}'Just if someone struggles like me with default and server_default in combination with a JSONB-column, what seems to work is the following:
from sqlalchemy import text
info = Column(JSONB, default=text("'{}'::jsonb"), server_default=text("'{}'::jsonb"))
The methods above (default=dict or default=lambda: {}) did not work for me. Especially in combination with alembic. I always got the error:
sqlalchemy.exc.ArgumentError: Argument 'arg' is expected to be one of type '<class 'str'>' or '<class 'sqlalchemy.sql.elements.ClauseElement'>' or '<class 'sqlalchemy.sql.elements.TextClause'>', got '<class 'type'>' (or function instead of type for the lambda).
default in alembic migration scripts is just meaningless - alembic never performs INSERTs or UPDATEs, and default is used only when there is no value for column at INSERT or UPDATE. See: docs.sqlalchemy.org/en/14/core/defaults.html. As a rule of thumb, you should use only DDL-producing SQLA-constructs (like tables, columns) in your migration scripts.default or server_default here works, and I didn't need to add ::jsonb either. For anyone who has a non-empty default, here's an example: privileges = db.Column(JSONB, nullable=False, default=text(f"'{json.dumps(default_privileges)}'")) - where default_privileges is any dict defined for this purposeBetter to use just dict constructor:
info = Column(JSON, default=dict)
Also, work perfectly for other types:
created = Column(DateTime, default=datetime.utcnow)
dictinstance is being used across all instances of your model. Trydefault=lambda: {}.