======================================================================
Serialchemy
======================================================================
.. image:: https://img.shields.io/pypi/v/serialchemy.svg
:target: https://pypi.python.org/pypi/serialchemy
.. image:: https://img.shields.io/pypi/pyversions/serialchemy.svg
:target: https://pypi.org/project/serialchemy
.. image:: https://github.com/ESSS/serialchemy/workflows/build/badge.svg
:target: https://github.com/ESSS/serialchemy/actions
.. image:: https://codecov.io/gh/ESSS/serialchemy/branch/master/graph/badge.svg
:target: https://codecov.io/gh/ESSS/serialchemy
.. image:: https://img.shields.io/readthedocs/serialchemy.svg
:target: https://serialchemy.readthedocs.io/en/latest/
.. image:: https://sonarcloud.io/api/project_badges/measure?project=ESSS_serialchemy&metric=alert_status
:target: https://sonarcloud.io/project/overview?id=ESSS_serialchemy
SQLAlchemy model serialization.
===============================
Motivation
----------
**Serialchemy** was developed as a module of Flask-RESTAlchemy_, a lib to create Restful APIs
using Flask and SQLAlchemy. We first tried marshmallow-sqlalchemy_, probably the most
well-known lib for SQLAlchemy model serialization, but we faced `issues related to nested
models <https://github.com/marshmallow-code/marshmallow-sqlalchemy/issues/67>`_. We also think
that is possible to build a simpler and more maintainable solution by having SQLAlchemy_ in
mind from the ground up, as opposed to marshmallow-sqlalchemy_ that had to be
designed and built on top of marshmallow_.
.. _SQLAlchemy: www.sqlalchemy.org
.. _marshmallow-sqlalchemy: http://marshmallow-sqlalchemy.readthedocs.io
.. _marshmallow: https://marshmallow.readthedocs.io
.. _Flask-RESTAlchemy: https://github.com/ESSS/flask-restalchemy
How to Use it
-------------
Serializing Generic Types
.........................
Suppose we have an `Employee` SQLAlchemy_ model declared:
.. code-block:: python
class Employee(Base):
__tablename__ = "Employee"
id = Column(Integer, primary_key=True)
fullname = Column(String)
admission = Column(DateTime, default=datetime(2000, 1, 1))
company_id = Column(ForeignKey("Company.id"))
company = relationship(Company)
company_name = column_property(
select([Company.name]).where(Company.id == company_id)
)
password = Column(String)
`Generic Types`_ are automatically serialized by `ModelSerializer`:
.. code-block:: python
from serialchemy import ModelSerializer
emp = Employee(fullname="Roberto Silva", admission=datetime(2019, 4, 2))
serializer = ModelSerializer(Employee)
serializer.dump(emp)
# >>
{
"id": None,
"fullname": "Roberto Silva",
"admission": "2019-04-02T00:00:00",
"company_id": None,
"company_name": None,
"password": None,
}
New items can be deserialized by the same serializer:
.. code-block:: python
new_employee = {"fullname": "Jobson Gomes", "admission": "2018-02-03"}
serializer.load(new_employee)
# >> <Employee object at 0x000001C119DE3940>
Serializers do not commit into the database. You must do this by yourself:
.. code-block:: python
emp = serializer.load(new_employee)
session.add(emp)
session.commit()
.. _`Generic Types`: https://docs.sqlalchemy.org/en/rel_1_2/core/type_basics.html#generic-types
Custom Serializers
..................
For anything beyond `Generic Types`_ we must extend the `ModelSerializer` class:
.. code-block:: python
class EmployeeSerializer(ModelSerializer):
password = Field(load_only=True) # passwords should be only deserialized
company = NestedModelField(Company) # dump company as nested object
serializer = EmployeeSerializer(Employee)
serializer.dump(emp)
# >>
{
"id": 1,
"fullname": "Roberto Silva",
"admission": "2019-04-02T00:00:00",
"company": {"id": 3, "name": "Acme Co"},
}
Extend Polymorphic Serializer
+++++++++++++++++++++++++++++
One of the possibilities is to serialize SQLalchemy joined table inheritance and
it child tables as well. To do such it's necessary to set a variable with
the desired model class name. Take this `Employee` class with for instance and let us
assume it have a joined table inheritance:
.. code-block:: python
class Employee(Base):
...
type = Column(String(50))
__mapper_args__ = {"polymorphic_identity": "employee", "polymorphic_on": type}
class Engineer(Employee):
__tablename__ = "Engineer"
id = Column(Integer, ForeignKey("employee.id"), primary_key=True)
association = relationship(Association)
__mapper_args__ = {
"polymorphic_identity": "engineer",
}
To use a extended `ModelSerializer` class on the `Engineer` class, you should create
the serializer as it follows:
.. code-block:: python
class EmployeeSerializer(
PolymorphicModelSerializer
): # Since this class will be polymorphic
password = Field(load_only=True)
company = NestedModelField(Company)
class EngineerSerializer(EmployeeSerializer):
__model_class__ = Engineer # This is the table Serialchemy will refer to
association = NestedModelField(Association)
Contributing
------------
For guidance on setting up a development environment and how to make a
contribution to serialchemy, see the `contributing guidelines`_.
.. _contributing guidelines: https://github.com/ESSS/serialchemy/blob/master/CONTRIBUTING.rst
Release
-------
A reminder for the maintainers on how to make a new release.
Note that the VERSION should folow the semantic versioning as X.Y.Z Ex.: v1.0.5
Create a release-VERSION branch from upstream/master.
Update CHANGELOG.rst.
Push a branch with the changes.
Once all builds pass, push a VERSION tag to upstream. Ex: git tag v1.0.5; git push origin --tags
Merge the PR.
History
=======
1.0.2 (2025-07-08)
------------------
* Adjust PolymorphicModelSerializer to accept a pure Enum as polymorphic identity
1.0.1 (2023-17-11)
------------------
* Fix license placement on setup.py
1.0.0 (2023-14-11)
------------------
* Add support for SQLAlchemy imperative (classical) mapping
* Drop support for Python versions bellow 3.8
* Drop support for SQLAlchemy 1.3
0.4.0 (2023-12-11)
------------------
* Fix to get model attribute name instead of table column name on polymorphic serializer
* Extends the PolymorphicModelSerializer to accept also column descriptors when searching
for the polymorphic column key.
* Add support for serialization of Python Enums
* Change PolymorphicModelSerializer to support inherited models of inherited models
* Change Field to use a default serializer for not None values
* Added support for sqlalchemy 1.4
* Add EnumKeySerializer
0.3.0 (2019-17-07)
------------------
* Add the composite fields to list of properties of model, to serialize that fields if it type is in EXTRA_SERIALIZERS.
* Fix error for SQLAlchemy composite attributes
* Added free functions dump and load so users can quickly dump a SQLAlchemy model without having to instancialize
ModelSerializer.
0.2.0 (2019-03-22)
------------------
* Fix: Error when deserializing of nested models when SQLAlchemy model primary
key attribute name differs from the column name
* Allow EXTRA_SERIALIZERS to be defined in runtime
* Check if a session was given when serializing/deserializing nested fields
0.1.0 (2019-02-12)
------------------
* First release on PyPI.
Raw data
{
"_id": null,
"home_page": "https://github.com/ESSS/serialchemy",
"name": "serialchemy",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "serialchemy",
"author": "ESSS",
"author_email": "foss@esss.co",
"download_url": "https://files.pythonhosted.org/packages/49/d9/1f38cded4b938eb308c4fee0d229d915dda3323b96b7d30d4843af403243/serialchemy-1.0.2.tar.gz",
"platform": null,
"description": "======================================================================\nSerialchemy\n======================================================================\n\n\n.. image:: https://img.shields.io/pypi/v/serialchemy.svg\n :target: https://pypi.python.org/pypi/serialchemy\n\n.. image:: https://img.shields.io/pypi/pyversions/serialchemy.svg\n :target: https://pypi.org/project/serialchemy\n\n.. image:: https://github.com/ESSS/serialchemy/workflows/build/badge.svg\n :target: https://github.com/ESSS/serialchemy/actions\n\n.. image:: https://codecov.io/gh/ESSS/serialchemy/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/ESSS/serialchemy\n\n.. image:: https://img.shields.io/readthedocs/serialchemy.svg\n :target: https://serialchemy.readthedocs.io/en/latest/\n\n.. image:: https://sonarcloud.io/api/project_badges/measure?project=ESSS_serialchemy&metric=alert_status\n :target: https://sonarcloud.io/project/overview?id=ESSS_serialchemy\n\n\nSQLAlchemy model serialization.\n===============================\n\nMotivation\n----------\n\n**Serialchemy** was developed as a module of Flask-RESTAlchemy_, a lib to create Restful APIs\nusing Flask and SQLAlchemy. We first tried marshmallow-sqlalchemy_, probably the most\nwell-known lib for SQLAlchemy model serialization, but we faced `issues related to nested\nmodels <https://github.com/marshmallow-code/marshmallow-sqlalchemy/issues/67>`_. We also think\nthat is possible to build a simpler and more maintainable solution by having SQLAlchemy_ in\nmind from the ground up, as opposed to marshmallow-sqlalchemy_ that had to be\ndesigned and built on top of marshmallow_.\n\n.. _SQLAlchemy: www.sqlalchemy.org\n.. _marshmallow-sqlalchemy: http://marshmallow-sqlalchemy.readthedocs.io\n.. _marshmallow: https://marshmallow.readthedocs.io\n.. _Flask-RESTAlchemy: https://github.com/ESSS/flask-restalchemy\n\nHow to Use it\n-------------\n\nSerializing Generic Types\n.........................\n\nSuppose we have an `Employee` SQLAlchemy_ model declared:\n\n.. code-block:: python\n\n class Employee(Base):\n __tablename__ = \"Employee\"\n\n id = Column(Integer, primary_key=True)\n fullname = Column(String)\n admission = Column(DateTime, default=datetime(2000, 1, 1))\n company_id = Column(ForeignKey(\"Company.id\"))\n company = relationship(Company)\n company_name = column_property(\n select([Company.name]).where(Company.id == company_id)\n )\n password = Column(String)\n\n`Generic Types`_ are automatically serialized by `ModelSerializer`:\n\n.. code-block:: python\n\n from serialchemy import ModelSerializer\n\n emp = Employee(fullname=\"Roberto Silva\", admission=datetime(2019, 4, 2))\n\n serializer = ModelSerializer(Employee)\n serializer.dump(emp)\n\n # >>\n {\n \"id\": None,\n \"fullname\": \"Roberto Silva\",\n \"admission\": \"2019-04-02T00:00:00\",\n \"company_id\": None,\n \"company_name\": None,\n \"password\": None,\n }\n\nNew items can be deserialized by the same serializer:\n\n.. code-block:: python\n\n new_employee = {\"fullname\": \"Jobson Gomes\", \"admission\": \"2018-02-03\"}\n serializer.load(new_employee)\n\n # >> <Employee object at 0x000001C119DE3940>\n\nSerializers do not commit into the database. You must do this by yourself:\n\n.. code-block:: python\n\n emp = serializer.load(new_employee)\n session.add(emp)\n session.commit()\n\n.. _`Generic Types`: https://docs.sqlalchemy.org/en/rel_1_2/core/type_basics.html#generic-types\n\nCustom Serializers\n..................\n\nFor anything beyond `Generic Types`_ we must extend the `ModelSerializer` class:\n\n.. code-block:: python\n\n class EmployeeSerializer(ModelSerializer):\n\n password = Field(load_only=True) # passwords should be only deserialized\n company = NestedModelField(Company) # dump company as nested object\n\n\n serializer = EmployeeSerializer(Employee)\n serializer.dump(emp)\n # >>\n {\n \"id\": 1,\n \"fullname\": \"Roberto Silva\",\n \"admission\": \"2019-04-02T00:00:00\",\n \"company\": {\"id\": 3, \"name\": \"Acme Co\"},\n }\n\n\nExtend Polymorphic Serializer\n+++++++++++++++++++++++++++++\nOne of the possibilities is to serialize SQLalchemy joined table inheritance and\nit child tables as well. To do such it's necessary to set a variable with\nthe desired model class name. Take this `Employee` class with for instance and let us\nassume it have a joined table inheritance:\n\n.. code-block:: python\n\n class Employee(Base):\n ...\n type = Column(String(50))\n\n __mapper_args__ = {\"polymorphic_identity\": \"employee\", \"polymorphic_on\": type}\n\n\n class Engineer(Employee):\n __tablename__ = \"Engineer\"\n id = Column(Integer, ForeignKey(\"employee.id\"), primary_key=True)\n association = relationship(Association)\n\n __mapper_args__ = {\n \"polymorphic_identity\": \"engineer\",\n }\n\nTo use a extended `ModelSerializer` class on the `Engineer` class, you should create\nthe serializer as it follows:\n\n.. code-block:: python\n\n class EmployeeSerializer(\n PolymorphicModelSerializer\n ): # Since this class will be polymorphic\n\n password = Field(load_only=True)\n company = NestedModelField(Company)\n\n\n class EngineerSerializer(EmployeeSerializer):\n __model_class__ = Engineer # This is the table Serialchemy will refer to\n association = NestedModelField(Association)\n\nContributing\n------------\n\nFor guidance on setting up a development environment and how to make a\ncontribution to serialchemy, see the `contributing guidelines`_.\n\n.. _contributing guidelines: https://github.com/ESSS/serialchemy/blob/master/CONTRIBUTING.rst\n\n\nRelease\n-------\nA reminder for the maintainers on how to make a new release.\n\nNote that the VERSION should folow the semantic versioning as X.Y.Z Ex.: v1.0.5\n\nCreate a release-VERSION branch from upstream/master.\nUpdate CHANGELOG.rst.\nPush a branch with the changes.\nOnce all builds pass, push a VERSION tag to upstream. Ex: git tag v1.0.5; git push origin --tags\nMerge the PR.\n\n\nHistory\n=======\n1.0.2 (2025-07-08)\n------------------\n* Adjust PolymorphicModelSerializer to accept a pure Enum as polymorphic identity\n\n1.0.1 (2023-17-11)\n------------------\n* Fix license placement on setup.py\n\n1.0.0 (2023-14-11)\n------------------\n* Add support for SQLAlchemy imperative (classical) mapping\n* Drop support for Python versions bellow 3.8\n* Drop support for SQLAlchemy 1.3\n\n0.4.0 (2023-12-11)\n------------------\n* Fix to get model attribute name instead of table column name on polymorphic serializer\n* Extends the PolymorphicModelSerializer to accept also column descriptors when searching\n for the polymorphic column key.\n* Add support for serialization of Python Enums\n* Change PolymorphicModelSerializer to support inherited models of inherited models\n* Change Field to use a default serializer for not None values\n* Added support for sqlalchemy 1.4\n* Add EnumKeySerializer\n\n0.3.0 (2019-17-07)\n------------------\n* Add the composite fields to list of properties of model, to serialize that fields if it type is in EXTRA_SERIALIZERS.\n* Fix error for SQLAlchemy composite attributes\n* Added free functions dump and load so users can quickly dump a SQLAlchemy model without having to instancialize\n ModelSerializer.\n\n0.2.0 (2019-03-22)\n------------------\n\n* Fix: Error when deserializing of nested models when SQLAlchemy model primary\n key attribute name differs from the column name\n* Allow EXTRA_SERIALIZERS to be defined in runtime\n* Check if a session was given when serializing/deserializing nested fields\n\n0.1.0 (2019-02-12)\n------------------\n\n* First release on PyPI.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Serializers for SQLAlchemy models.",
"version": "1.0.2",
"project_urls": {
"Homepage": "https://github.com/ESSS/serialchemy"
},
"split_keywords": [
"serialchemy"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "b5ab3911713d21332275a0d6c8210759532c92f2fcb13298f8e6f4e64018b3f2",
"md5": "d4f3585eb54c115bb8aa56ae6c18e4e1",
"sha256": "f70cba0af3618dcdabf2bbaf4d1253427cbbeabcb960ab436417fe1240f7c555"
},
"downloads": -1,
"filename": "serialchemy-1.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d4f3585eb54c115bb8aa56ae6c18e4e1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 37330,
"upload_time": "2025-08-07T20:48:41",
"upload_time_iso_8601": "2025-08-07T20:48:41.686029Z",
"url": "https://files.pythonhosted.org/packages/b5/ab/3911713d21332275a0d6c8210759532c92f2fcb13298f8e6f4e64018b3f2/serialchemy-1.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "49d91f38cded4b938eb308c4fee0d229d915dda3323b96b7d30d4843af403243",
"md5": "fa217cb7f34dcd1fcd3b8d0a8854036f",
"sha256": "344c0f54cf6962dac00e87c380e40d608d38610b82909e9c1237e0148874ec1c"
},
"downloads": -1,
"filename": "serialchemy-1.0.2.tar.gz",
"has_sig": false,
"md5_digest": "fa217cb7f34dcd1fcd3b8d0a8854036f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 30805,
"upload_time": "2025-08-07T20:48:42",
"upload_time_iso_8601": "2025-08-07T20:48:42.607269Z",
"url": "https://files.pythonhosted.org/packages/49/d9/1f38cded4b938eb308c4fee0d229d915dda3323b96b7d30d4843af403243/serialchemy-1.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-07 20:48:42",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ESSS",
"github_project": "serialchemy",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "serialchemy"
}