marshmallow-code / marshmallow-code/marshmallow
Object class and schema definition combined, ORM-style
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 7.2k
- Forks
- 738
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 7
Description
Hello all,
I would like to ask if there has been consideration about adding a model that allows for data storage and serialization/deserialization in one. This is a pretty common use case, avoiding redundancy between defining schemas and the data they produce. This could be done via an ORM-style model like SQLAlchemy has.
Something like this was discussed before (https://github.com/marshmallow-code/marshmallow/issues/1043) but since the recipe is simple and useful, I can see value adding it to marshmallow.
There are some libraries that accomplish similar goals, but they have some drawbacks:
- marshmallow-dataclass is available but requires some boilerplate, plus some workarounds (e.g. must use dataclass fields rather than marshmallow fields)
- marshmallow-objects exists but is currently archived
A possible API could look like the following:
from datetime import datetime
from marshmallow import MarshModel, INCLUDE, fields, ValidationError
class UserModel(MarshModel):
__meta_args__ = {'unknown': INCLUDE}
name: str = fields.Str()
email: str = fields.Email()
created_at: datetime = fields.DateTime()
@validates('email'):
def validate_email(self, value: Any) -> None:
if '@' not in value:
raise ValidationError('Not an email address!')
class BlogModel(MarshModel):
title: str = fields.String()
author: dict = fields.Nested(UserModel)
user_data = {"name": "Ronnie", "email": "ronnie@stones.com"}
user = UserModel.load(user_data)
blog = BlogModel(title="Something Completely Different", author=user)
blog.dump()
pprint(result)
# {'title': 'Something Completely Different',
# 'author': {'name': 'Ronnie',
# 'email': ronnie@stones.org',
# 'created_at': '2021-08-17T14:58:57.600623+00:00'}}
MarshModel would require:
- Something that creates a schema from the defined class (maybe via an init_subclass hook to store it as cls.__schema or something)
- Implicit
__init__function in similar way to dataclasses - Implicit
load()classmethod that returns an instance - Typing - something similar to how SQLA handles this https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html#installation
If there is interest, I may be able to submit a PR
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the linked discussion in issue #1043 and the proposed MarshModel API; no implementation files or tests are identified here. Done would require an agreed scope and design for combined schema/model definitions, implicit initialization and load behavior, nested models, validation, and typing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100