### Running the Inflection Example Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/inflection.rst Execute the Python script using 'uv' to see the data inflection in action. This command assumes 'uv' is installed and the script is in the examples directory. ```shell $ uv run examples/inflection_example.py Loaded data: {'first_name': 'David', 'last_name': 'Bowie'} Dumped data: {'firstName': 'David', 'lastName': 'Bowie'} ``` -------------------------------- ### Install httpie CLI Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/quotes_api.rst Command to install the httpie command-line HTTP client using uv. ```shell $ uv tool install httpie ``` -------------------------------- ### Valid package.json Example Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/validating_package_json.rst This is a sample package.json file that conforms to the defined schema. ```json { "name": "dunderscore", "version": "1.2.3", "description": "The Pythonic JavaScript toolkit", "main": "index.js", "license": "MIT", "scripts": { "test": "pest" }, "devDependencies": { "pest": "^23.4.1" } } ``` -------------------------------- ### Install Marshmallow Source: https://github.com/marshmallow-code/marshmallow/blob/dev/README.rst Installs the marshmallow library using pip. Ensure you have pip installed and updated for the latest version. ```shell $ pip install -U marshmallow ``` -------------------------------- ### Install Latest Development Version from GitHub Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/install.rst Get the bleeding-edge development version of marshmallow directly from its GitHub repository. ```shell $ pip install -U git+https://github.com/marshmallow-code/marshmallow.git@dev ``` -------------------------------- ### GET all quotes Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/quotes_api.rst Example of sending a GET request to the /quotes endpoint to retrieve a list of all quotes currently in the system. ```shell $ http :5000/quotes/ ``` -------------------------------- ### Install Latest Pre-release Marshmallow from PyPI Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/install.rst Install the latest pre-release version of marshmallow by adding the --pre flag. ```shell $ pip install -U marshmallow --pre ``` -------------------------------- ### Run the Flask Quotes API Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/quotes_api.rst Command to start the Flask development server for the quotes API application. ```shell $ uv run examples/flask_example.py ``` -------------------------------- ### Invalid package.json Example Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/validating_package_json.rst This is an example of an invalid package.json file containing errors in the 'homepage' and 'version' fields. ```json { "name": "dunderscore", "version": "invalid-version", "description": "The Pythonic JavaScript toolkit", "main": "index.js", "license": "MIT", "scripts": { "test": "pest" }, "devDependencies": { "pest": "^23.4.1" }, "homepage": "not-a-url" } ``` -------------------------------- ### Custom Field Serialization and Deserialization Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Example of defining a custom field by overriding _serialize. Custom fields now implement _serialize and _deserialize methods for custom behavior. ```python from marshmallow import fields, MarshallingError class PasswordField(fields.Field): def _serialize(self, value, attr, obj): if not value or len(value) < 6: raise MarshallingError("Password must be greater than 6 characters.") return str(value).strip() # Similarly, you can override the _deserialize method ``` -------------------------------- ### GET quotes for a specific author Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/quotes_api.rst Example of sending a GET request to the /authors/{id} endpoint to retrieve an author's details along with all their associated quotes. ```shell $ http :5000/authors/1 ``` -------------------------------- ### Dump Nested Data with Marshmallow Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/nesting.rst Demonstrates how to dump data using the defined nested schemas. This example shows the output structure for both book and author data, illustrating how nesting and exclusions work. ```python from pprint import pprint from mymodels import Author, Book author = Author(name="William Faulkner") book = Book(title="As I Lay Dying", author=author) book_result = BookSchema().dump(book) pprint(book_result, indent=2) # { # "id": 124, # "title": "As I Lay Dying", # "author": { # "id": 8, # "name": "William Faulkner" # } # } author_result = AuthorSchema().dump(author) pprint(author_result, indent=2) # { # "id": 8, # "name": "William Faulkner", # "books": [ # { # "id": 124, # "title": "As I Lay Dying" # } # ] # } ``` -------------------------------- ### POST a new quote Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/quotes_api.rst Example of sending a POST request to the /quotes endpoint to add a new quote with author and content. ```shell $ http POST :5000/quotes/ author="Tim Peters" content="Beautiful is better than ugly." ``` ```shell $ http POST :5000/quotes/ author="Tim Peters" content="Now is better than never." ``` ```shell $ http POST :5000/quotes/ author="Peter Hintjens" content="Simplicity is always better than functionality." ``` -------------------------------- ### Object Deserialization (1.0 vs 2.0 API) Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst The `make_object` method for deserializing to an object has been deprecated. Use a `post_load` method instead, as shown in the 2.0 API example. ```python # 1.0 from marshmallow import Schema, fields, post_load class UserSchema(Schema): name = fields.Str() created_at = fields.DateTime() def make_object(self, data): return User(**data) # 2.0 from marshmallow import Schema, fields, post_load class UserSchema(Schema): name = fields.Str() created_at = fields.DateTime() @post_load def make_user(self, data): ``` -------------------------------- ### Schema Prefix Removal and Alternative Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst The `prefix` parameter for `Schema` has been removed in Marshmallow 3.x. The equivalent functionality can now be achieved using a `post_dump` method, as shown in the example. ```python # 2.x class MySchema(Schema): f1 = fields.Raw() f2 = fields.Raw() MySchema(prefix="pre_").dump({"f1": "one", "f2": "two"}) # {'pre_f1': 'one', '_pre_f2': 'two'} # 3.x class MySchema(Schema): f1 = fields.Raw() f2 = fields.Raw() @post_dump def prefix_usr(self, data): return {"usr_{}".format(k): v for k, v in iteritems(data)} MySchema().dump({"f1": "one", "f2": "two"}) # {'pre_f1': 'one', '_pre_f2': 'two'} ``` -------------------------------- ### Define Application Schema with Custom Meta Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/extending/custom_options.rst Inherit from the custom schema class and define the custom Meta options ('name', 'plural_name') within an inner Meta class. This example shows a UserSchema. ```python from marshmallow import Schema, SchemaOpts, pre_load, post_dump, fields class NamespaceOpts(SchemaOpts): """Same as the default class Meta options, but adds "name" and "plural_name" options for enveloping. """ def __init__(self, meta, **kwargs): SchemaOpts.__init__(self, meta, **kwargs) self.name = getattr(meta, "name", None) self.plural_name = getattr(meta, "plural_name", self.name) class NamespacedSchema(Schema): OPTIONS_CLASS = NamespaceOpts @pre_load(pass_many=True) def unwrap_envelope(self, data, many, **kwargs): key = self.opts.plural_name if many else self.opts.name return data[key] @post_dump(pass_many=True) def wrap_with_envelope(self, data, many, **kwargs): key = self.opts.plural_name if many else self.opts.name return {key: data} class UserSchema(NamespacedSchema): name = fields.String() email = fields.Email() class Meta: name = "user" plural_name = "users" ``` -------------------------------- ### Use standard library for date/time utilities Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Marshmallow 4.x removes ISO 8601 and RFC 822 utilities from marshmallow.utils, favoring standard library implementations. The example shows the 3.x imports and usage compared to 4.x. ```python # 3.x import datetime as dt from marshmallow.utils import ( from_iso_date, from_iso_time, from_iso_datetime, to_iso_date, to_iso_time, isoformat, from_rfc, rfc_format, ) from_iso_date("2013-11-10") from_iso_time("01:23:45") from_iso_datetime("2013-11-10T01:23:45") to_iso_date(dt.date(2013, 11, 10)) to_iso_time(dt.time(1, 23, 45)) isoformat(dt.datetime(2013, 11, 10, 1, 23, 45)) from_rfc("Sun, 10 Nov 2013 01:23:45 -0000") rfc_format(dt.datetime(2013, 11, 10, 1, 23, 45)) # 4.x import datetime as dt import email.utils dt.date.fromisoformat("2013-11-10") dt.time.fromisoformat("01:23:45") dt.datetime.fromisoformat("2013-11-10T01:23:45") dt.date(2013, 11, 10).isoformat() dt.time(1, 23, 45).isoformat() dt.datetime(2013, 11, 10, 1, 23, 45).isoformat() email.utils.parsedate_to_datetime("Sun, 10 Nov 2013 01:23:45 -0000") email.utils.format_datetime(dt.datetime(2013, 11, 10, 1, 23, 45)) ``` -------------------------------- ### Using Built-in Validators Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/quickstart.rst Illustrates using built-in validators like `Length`, `OneOf`, and `Range` to enforce constraints on field values. This example shows how errors are reported for fields violating these constraints. ```python from pprint import pprint from marshmallow import Schema, fields, validate, ValidationError class UserSchema(Schema): name = fields.Str(validate=validate.Length(min=1)) permission = fields.Str(validate=validate.OneOf(["read", "write", "admin"])) age = fields.Int(validate=validate.Range(min=18, max=40)) in_data = {"name": "", "permission": "invalid", "age": 71} try: UserSchema().load(in_data) except ValidationError as err: pprint(err.messages) # {'age': ['Must be greater than or equal to 18 and less than or equal to 40.'], # 'name': ['Shorter than minimum length 1.'], # 'permission': ['Must be one of: read, write, admin.']} ``` -------------------------------- ### Custom SchemaOpts Initialization (2.x vs 3.x) Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Illustrates the difference in initializing a custom SchemaOpts class between Marshmallow 2.x and 3.x, highlighting the addition of the 'ordered' argument in 3.x. ```python from marshmallow import SchemaOpts # 2.x class CustomOpts(SchemaOpts): def __init__(self, meta): super().__init__(meta) self.custom_option = getattr(meta, "meta", False) # 3.x class CustomOpts(SchemaOpts): def __init__(self, meta, ordered=False): super().__init__(meta, ordered) self.custom_option = getattr(meta, "meta", False) ``` -------------------------------- ### Combining Pre-Processing Steps in One Method Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/extending/pre_and_post_processing.rst Illustrates the recommended approach for ensuring processing order by combining multiple pre-processing steps into a single @pre_load method. This avoids issues with the non-guaranteed invocation order of separate decorated methods. ```python from marshmallow import Schema, fields, pre_load # YES class MySchema(Schema): field_a = fields.Raw() @pre_load def preprocess(self, data, **kwargs): step1_data = self.step1(data) step2_data = self.step2(step1_data) return step2_data def step1(self, data): ... # Depends on step1 def step2(self, data): ... ``` -------------------------------- ### Decorator Argument Handling (2.x vs 3.x) Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Illustrates the change in decorated methods (pre_load, post_load, etc.) between Marshmallow 2.x and 3.x, where 3.x requires accepting **kwargs to handle 'many' and 'partial' arguments. ```python # 2.x class UserSchema(Schema): name = fields.Str() slug = fields.Str() @pre_load def slugify_name(self, in_data): in_data["slug"] = in_data["slug"].lower().strip().replace(" ", "-") return in_data # 3.x class UserSchema(Schema): name = fields.Str() slug = fields.Str() @pre_load def slugify_name(self, in_data, **kwargs): in_data["slug"] = in_data["slug"].lower().strip().replace(" ", "-") return in_data ``` -------------------------------- ### Basic Pre-Load for Data Unwrapping Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/extending/pre_and_post_processing.rst Demonstrates a basic @pre_load method to unwrap nested data, expecting a 'data' key. Raises ValidationError if the key is missing. ```python from marshmallow import Schema, fields, ValidationError, pre_load class BandSchema(Schema): name = fields.Str() @pre_load def unwrap_envelope(self, data, **kwargs): if "data" not in data: raise ValidationError('Input data must have a "data" key.') return data["data"] ``` -------------------------------- ### FormattedString Field Removal Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst `fields.FormattedString` is removed in Marshmallow 3.x. Use `fields.Function` or `fields.Method` for similar functionality, as demonstrated by the example. ```python # 2.x class MySchema(Schema): full_name = fields.FormattedString("{first_name} {last_name}") # 3.x class MySchema(Schema): full_name = fields.Function(lambda u: f"{u.first_name} {u.last_name}") ``` -------------------------------- ### Handling Different Load and Dump Keys Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst In Marshmallow 3.x, use separate schemas to specify different keys for loading and dumping. ```python from marshmallow import Schema, fields # 2.x class UserSchema(Schema): email = fields.Email(load_from="CamelCasedEmail", dump_to="snake_case_email") # 3.x class BaseUserSchema(Schema): id = fields.Str() class LoadUserSchema(BaseUserSchema): email = fields.Email(data_key="CamelCasedEmail") class DumpUserSchema(BaseUserSchema): email = fields.Email(data_key="snake_case_email") ``` -------------------------------- ### Marshmallow Function/Method Field Deserialize Parameter Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Shows how to use the `deserialize` parameter with `fields.Function` and `fields.Method` when the `serialize` parameter is not provided, starting from Marshmallow 2.3. ```python lowername = fields.Function(deserialize=lambda name: name.lower()) # or lowername = fields.Method(deserialize="lowername") ``` -------------------------------- ### Partial Loading with Specific Fields Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/quickstart.rst Shows how to perform partial loading by specifying a tuple of field names to ignore required validation for. This is useful when a schema is used in multiple contexts. ```python class UserSchema(Schema): name = fields.String(required=True) age = fields.Integer(required=True) result = UserSchema().load({"age": 42}, partial=("name",)) # OR UserSchema(partial=('name',)).load({'age': 42}) print(result) # => {'age': 42} ``` -------------------------------- ### Rename 'schema' to 'parent' in _bind_to_schema Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Custom fields defining a _bind_to_schema method should rename the 'schema' argument to 'parent' in Marshmallow 4.x. The example illustrates this change. ```python from marshmallow import fields # 3.x class MyField(fields.Field): def _bind_to_schema(self, field_name: str, schema: Schema | Field): ... # 4.x class MyField(fields.Field[int]): def _bind_to_schema(self, field_name: str, parent: Schema | Field): ... ``` -------------------------------- ### Pre/Post Processing Hooks (1.0 vs 2.0 API) Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Marshmallow 2.0 introduced decorator-based pre/post processing hooks (`pre_load`, `post_load`, `pre_dump`, `post_dump`), replacing the older `Schema.preprocessor` and `Schema.data_handler`. ```python # 1.0 API from marshmallow import Schema, fields class ExampleSchema(Schema): field_a = fields.Int() @ExampleSchema.preprocessor def increment(schema, data): data["field_a"] += 1 return data @ExampleSchema.data_handler def decrement(schema, data, obj): data["field_a"] -= 1 return data ``` ```python # 2.0 API from marshmallow import Schema, fields, pre_load, post_dump class ExampleSchema(Schema): field_a = fields.Int() @pre_load def increment(self, data): data["field_a"] += 1 return data @post_dump def decrement(self, data): data["field_a"] -= 1 return data ``` -------------------------------- ### Python Schema for Camel-Cased Keys Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/examples/inflection.rst This schema uses the on_bind_field hook to convert snake_case field names to camelCase for output and vice-versa for input. It requires Marshmallow to be installed. ```python from marshmallow import Schema, fields def camel_case_field(field_name): return "".join( x.capitalize() or "_" for x in field_name.split("_") ).lower() class CamelCaseSchema(Schema): def on_bind_field(self, field_name, field_obj): field_obj.data_key = camel_case_field(field_name) class UserSchema(CamelCaseSchema): first_name = fields.Str(required=True) last_name = fields.Str(required=True) schema = UserSchema() # Example usage loaded_data = { "first_name": "David", "last_name": "Bowie", } print(f"Loaded data:\n{loaded_data}") dumped_data = schema.dump(loaded_data) print(f"Dumped data:\n{dumped_data}") loaded_from_camel = schema.load({"firstName": "David", "lastName": "Bowie"}) print(f"Loaded from camel:\n{loaded_from_camel}") ``` -------------------------------- ### Remove 'ordered' from SchemaOpts constructor Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst In Marshmallow 4.x, subclasses of SchemaOpts should remove the 'ordered' argument from their constructors. The example shows the 3.x and 4.x versions of a CustomOpts class. ```python class CustomOpts(SchemaOpts): def __init__(self, meta, ordered=False): super().__init__(meta, ordered=ordered) self.custom_option = getattr(meta, "custom_option", False) class CustomOpts(SchemaOpts): def __init__(self, meta): super().__init__(meta) self.custom_option = getattr(meta, "custom_option", False) ``` -------------------------------- ### Partial Loading with Nested Schemas Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/nesting.rst Shows how nested schemas inherit the 'partial' parameter for loading, allowing incomplete data. ```python class UserSchemaStrict(Schema): name = fields.String(required=True) email = fields.Email() created_at = fields.DateTime(required=True) class BlogSchemaStrict(Schema): title = fields.String(required=True) author = fields.Nested(UserSchemaStrict, required=True) schema = BlogSchemaStrict() blog = {"title": "Something Completely Different", "author": {}} result = schema.load(blog, partial=True) pprint(result) ``` -------------------------------- ### Specifying Default Values for Serialization and Deserialization Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/quickstart.rst Demonstrates the use of `load_default` for deserialization defaults and `dump_default` for serialization defaults. These are applied when the respective values are missing. ```python import uuid import datetime as dt from marshmallow import Schema, fields class UserSchema(Schema): id = fields.UUID(load_default=uuid.uuid1) birthdate = fields.DateTime(dump_default=dt.datetime(2017, 9, 29)) UserSchema().load({}) # {'id': UUID('337d946c-32cd-11e8-b475-0022192ed31b')} UserSchema().dump({}) # {'birthdate': '2017-09-29T00:00:00+00:00'} ``` -------------------------------- ### Rename 'pass_many' to 'pass_collection' in decorators Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst The 'pass_many' argument in Marshmallow decorators like @post_dump has been renamed to 'pass_collection' in version 4.x, with unchanged behavior. The example shows the syntax difference. ```python from marshmallow import Schema, fields, post_load # 3.x class MySchema(Schema): name = fields.Str() @post_dump(pass_many=True) def post_dump(self, data, many, **kwargs): ... # 4.x class MySchema(Schema): name = fields.Str() @post_dump(pass_collection=True) def post_dump(self, data, many, **kwargs): ... ``` -------------------------------- ### Partial Loading with Dot Delimiters Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/nesting.rst Demonstrates specifying partial loading for specific nested fields using dot notation. ```python author = {"name": "Monty"} blog = {"title": "Something Completely Different", "author": author} result = schema.load(blog, partial=("title", "author.created_at")) pprint(result) ``` -------------------------------- ### Customizing Attribute Access with get_attribute Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/extending/overriding_attribute_access.rst Override the `get_attribute` method to specify custom logic for retrieving values from objects. This example demonstrates using `dict.get` for schemas that only serialize dictionaries. ```python class UserDictSchema(Schema): name = fields.Str() email = fields.Email() # If we know we're only serializing dictionaries, we can # use dict.get for all input objects def get_attribute(self, obj, key, default): return obj.get(key, default) ``` -------------------------------- ### ContainsOnly Validator with Duplicates (3.x Behavior) Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Shows how the ContainsOnly validator in Marshmallow 3.x accepts duplicate values in the input list, unlike in 2.x. This example demonstrates the default behavior. ```python from marshmallow import validate validator = validate.ContainsOnly(["red", "blue"]) # in 2.x the following raises a ValidationError # in 3.x, no error is raised validator(["red", "red", "blue"]) ``` -------------------------------- ### Define and Use Marshmallow Schemas Source: https://github.com/marshmallow-code/marshmallow/blob/dev/README.rst Demonstrates how to define nested schemas for complex data structures and use the `dump` method to serialize Python dictionaries into primitive types. This is useful for preparing data for APIs. ```python from datetime import date from pprint import pprint from marshmallow import Schema, fields class ArtistSchema(Schema): name = fields.Str() class AlbumSchema(Schema): title = fields.Str() release_date = fields.Date() artist = fields.Nested(ArtistSchema()) bowie = dict(name="David Bowie") album = dict(artist=bowie, title="Hunky Dory", release_date=date(1971, 12, 17)) schema = AlbumSchema() result = schema.dump(album) pprint(result, indent=2) # { 'artist': {'name': 'David Bowie'}, # 'release_date': '1971-12-17', # 'title': 'Hunky Dory'} ``` -------------------------------- ### Remove 'ordered' Meta option Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst The 'ordered' Meta option in Marshmallow schemas is removed in version 3.26 and later, as order is preserved by default. The example shows the schema definition before and after this change. ```python from marshmallow import Schema, fields # <3.26 class MySchema(Schema): id = fields.Integer() class Meta: ordered = True # >=3.26 class MySchema(Schema): id = fields.Integer() ``` -------------------------------- ### Define Custom Schema Options Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/extending/custom_options.rst Create a custom SchemaOpts subclass to define new Meta options like 'name' and 'plural_name'. This class inherits from marshmallow.SchemaOpts and initializes the new options. ```python from marshmallow import Schema, SchemaOpts class NamespaceOpts(SchemaOpts): """Same as the default class Meta options, but adds "name" and "plural_name" options for enveloping. """ def __init__(self, meta, **kwargs): SchemaOpts.__init__(self, meta, **kwargs) self.name = getattr(meta, "name", None) self.plural_name = getattr(meta, "plural_name", self.name) ``` -------------------------------- ### Handling Unknown Fields by Including Them Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/quickstart.rst Configures a schema to include unknown fields in the output by setting `unknown = INCLUDE` in the `Meta` class. This allows processing of unexpected data. ```python from pprint import pprint from marshmallow import Schema, fields, INCLUDE class UserSchema(Schema): name = fields.Str() email = fields.Email() created_at = fields.DateTime() class Meta: unknown = INCLUDE result = UserSchema().load( { "name": "Monty", "email": "monty@python.org", "created_at": "2014-08-17T14:54:16.049594+00:00", "extra": "Not a field", } ) ``` -------------------------------- ### Using Context with Function and Method Fields Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/custom_fields.rst Utilize the `Context` class to provide environment-specific information to `Function` and `Method` fields during serialization. This allows fields to access external data like the current blog's author or title. ```python import typing from dataclasses import dataclass from marshmallow import Schema, fields from marshmallow.experimental.context import Context @dataclass class User: name: str @dataclass class Blog: title: str author: User class ContextDict(typing.TypedDict): blog: Blog class UserSchema(Schema): name = fields.String() is_author = fields.Function( lambda user: user == Context[ContextDict].get()["blog"].author ) likes_bikes = fields.Method("writes_about_bikes") def writes_about_bikes(self, user: User) -> bool: return "bicycle" in Context[ContextDict].get()["blog"].title.lower() ``` -------------------------------- ### Serialize Nested Data Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/nesting.rst Demonstrates serializing a Blog object with a nested User, showing the resulting dictionary. ```python from pprint import pprint user = User(name="Monty", email="monty@python.org") blog = Blog(title="Something Completely Different", author=user) result = BlogSchema().dump(blog) pprint(result) ``` -------------------------------- ### Partial Loading Ignoring All Required Fields Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/quickstart.rst Illustrates how to ignore all required field validations by setting `partial=True`. This allows loading data even if all required fields are missing. ```python class UserSchema(Schema): name = fields.String(required=True) age = fields.Integer(required=True) result = UserSchema().load({"age": 42}, partial=True) # OR UserSchema(partial=True).load({'age': 42}) print(result) # => {'age': 42} ``` -------------------------------- ### Handling ValidationError in Strict Mode Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst In Marshmallow 2.0, strict mode requires handling ValidationError instead of the deprecated UnmarshallingError when using Schema.load or Schema.dump. This example shows the try-except block for catching these errors. ```python from marshmallow import exceptions as exc schema = BandMemberSchema(strict=True) # 1.0 try: schema.load({"email": "invalid-email"}) except exc.UnmarshallingError as err: handle_error(err) # 2.0 try: schema.load({"email": "invalid-email"}) except exc.ValidationError as err: handle_error(err) ``` -------------------------------- ### DateTime Timezone Handling Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Marshmallow 3.x no longer converts naive datetimes to UTC during serialization. `LocalDateTime` is also removed. The example demonstrates the different serialization outputs for timezone-aware and naive datetimes between versions. ```python # 2.x class MySchema(Schema): x = fields.DateTime() y = fields.DateTime() z = fields.LocalDateTime() MySchema().dump( { "x": dt.datetime(2017, 9, 19), "y": dt.datetime(2017, 9, 19, tzinfo=dt.timezone(dt.timedelta(hours=2))), "z": dt.datetime(2017, 9, 19, tzinfo=dt.timezone(dt.timedelta(hours=2))), } ) # => {{'x': '2017-09-19T00:00:00+00:00', 'y': '2017-09-18T22:00:00+00:00', 'z': '2017-09-19T00:00:00+02:00'}} # 3.x class MySchema(Schema): x = fields.DateTime() y = fields.DateTime() MySchema().dump( { "x": dt.datetime(2017, 9, 19), "y": dt.datetime(2017, 9, 19, tzinfo=dt.timezone(dt.timedelta(hours=2))), } ) # => {{'x': '2017-09-19T00:00:00', 'y': '2017-09-19T00:00:00+02:00'}} ``` -------------------------------- ### Date and DateTime Formatting Changes Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst In Marshmallow 3.x, the `dateformat` Meta option applies to `fields.Date`, and `datetimeformat` is introduced for `fields.DateTime`. The example shows the difference in output for date and datetime serialization based on these formats. ```python # 2.x class MySchema(Schema): x = fields.DateTime() class Meta: dateformat = "%Y-%m" MySchema().dump({"x": dt.datetime(2017, 9, 19)}) # => {{'x': '2017-09'}} # 3.x class MySchema(Schema): x = fields.DateTime() y = fields.Date() class Meta: datetimeformat = "%Y-%m" dateformat = "%m-%d" MySchema().dump({"x": dt.datetime(2017, 9, 19), "y": dt.date(2017, 9, 19)}) # => {{'x': '2017-09', 'y': '09-19'}} ``` -------------------------------- ### Merging load_from and dump_to into data_key Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Demonstrates the consolidation of 'load_from' and 'dump_to' options into a single 'data_key' option in Marshmallow 3.x, used for specifying the key name in serialized and deserialized data. ```python # 2.x class UserSchema(Schema): # Example for 2.x would typically use load_from and dump_to separately # This snippet focuses on the 3.x change. # 3.x equivalent would be: # user_id = fields.Int(data_key="userId") ``` -------------------------------- ### Define Marshmallow Schemas for Nesting Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/nesting.rst Creates Marshmallow schemas for User and Blog, using Nested for the author relationship. ```python from marshmallow import Schema, fields class UserSchema(Schema): name = fields.String() email = fields.Email() created_at = fields.DateTime() class BlogSchema(Schema): title = fields.String() author = fields.Nested(UserSchema) ``` -------------------------------- ### Collection Validation Errors Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/quickstart.rst Shows how validation errors for a collection (list of dictionaries) are keyed by index. This example validates a list of band members, highlighting errors for an invalid email and a missing required field. ```python from pprint import pprint from marshmallow import Schema, fields, ValidationError class BandMemberSchema(Schema): name = fields.String(required=True) email = fields.Email() user_data = [ {"email": "mick@stones.com", "name": "Mick"}, {"email": "invalid", "name": "Invalid"}, # invalid email {"email": "keith@stones.com", "name": "Keith"}, {"email": "charlie@stones.com"}, # missing "name" ] try: BandMemberSchema(many=True).load(user_data) except ValidationError as err: pprint(err.messages) # {1: {'email': ['Not a valid email address.']}, # 3: {'name': ['Missing data for required field.']}} ``` -------------------------------- ### Schema Loading and Error Handling (2.x vs 3.x) Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Compares how data loading and validation errors were handled in Marshmallow 2.x (using 'strict' and returning (data, errors)) versus Marshmallow 3.x (raising ValidationError). ```python from marshmallow import ValidationError # 2.x schema = UserSchema() data, errors = schema.load({"name": "Monty", "email": "monty@python.org"}) # OR schema = UserSchema(strict=True) try: data, _ = schema.load({"name": "Monty", "email": "monty@python.org"}) except ValidationError as err: errors = err.messages valid_data = err.valid_data # 3.x schema = UserSchema() # There is only one right way try: data = schema.load({"name": "Monty", "email": "monty@python.org"}) except ValidationError as err: errors = err.messages valid_data = err.valid_data ``` -------------------------------- ### handle_error Argument Handling (2.x vs 3.x) Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Compares the signature of Schema.handle_error between Marshmallow 2.x and 3.x, highlighting the addition of **kwargs in 3.x to accommodate 'many' and 'partial' arguments. ```python # 2.x class UserSchema(Schema): def handle_error(self, exc, data): raise AppError("An error occurred with input: {0}".format(data)) # 3.x class UserSchema(Schema): def handle_error(self, exc, data, **kwargs): raise AppError("An error occurred with input: {0}".format(data)) ``` -------------------------------- ### Custom Field with Generic Type Argument Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Define a custom field by inheriting from fields.Field and specifying the internal type using a type argument. This example shows a PinCode field that serializes to a string and deserializes to a list of integers. ```python from marshmallow import fields class PinCode(fields.Field[list[int]]): """Field that serializes to a string of numbers and deserializes to a list of numbers. """ def _serialize(self, value, attr, obj, **kwargs): if value is None: return "" return "".join(str(d) for d in value) # The inferred return type is list[int] def _deserialize(self, value, attr, data, **kwargs): try: return [int(c) for c in value] except ValueError as error: raise ValidationError("Pin codes must contain only digits.") from error ``` -------------------------------- ### Attribute and DataKey Collision Handling Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Marshmallow 3.x enforces stricter checks for duplicate `attribute` or `data_key` values, raising a `ValueError` if collisions occur (excluding `dump_only` or `load_only` fields respectively). The examples show the behavior difference between 2.x and 3.x. ```python # 2.x class MySchema(Schema): f1 = fields.Raw() f2 = fields.Raw(attribute="f1") f3 = fields.Raw(attribute="f5") f4 = fields.Raw(attribute="f5") MySchema() # No error # 3.x class MySchema(Schema): f1 = fields.Raw() f2 = fields.Raw(attribute="f1") f3 = fields.Raw(attribute="f5") f4 = fields.Raw(attribute="f5") MySchema() # ValueError: 'Duplicate attributes: ['f1', 'f5]' class MySchema(Schema): f1 = fields.Raw() f2 = fields.Raw(attribute="f1", dump_only=True) f3 = fields.Raw(attribute="f5") f4 = fields.Raw(attribute="f5", dump_only=True) MySchema() # No error ``` -------------------------------- ### Object serialization using Schema.dump (1.0+) Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Marshmallow 1.0 introduced `Schema.dump` for serialization and `Schema.load` for deserialization, replacing the pre-1.0 constructor-based approach. ```python from marshmallow import Schema, fields class UserSchema(Schema): email = fields.Email() name = fields.String() user = User(email="monty@python.org", name="Monty Python") # 1.0 serializer = UserSchema() data, errors = serializer.dump(user) # OR result = serializer.dump(user) result.data # => serialized result result.errors # => errors # Pre-1.0 serialized = UserSchema(user) data = serialized.data errors = serialized.errors ``` -------------------------------- ### Define a User Model Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/quickstart.rst Define a basic Python dataclass to represent a user model. ```python from dataclasses import dataclass, field import datetime as dt @dataclass class User: name: str email: str created_at: dt.datetime = field(default_factory=dt.datetime.now) ``` -------------------------------- ### Pre-Load with Custom Error Key Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/extending/pre_and_post_processing.rst Shows how to specify a custom key for ValidationError messages during pre-processing by passing the key name to the ValidationError constructor. ```python from marshmallow import Schema, fields, ValidationError, pre_load class BandSchema(Schema): name = fields.Str() @pre_load def unwrap_envelope(self, data, **kwargs): if "data" not in data: raise ValidationError( 'Input data must have a "data" key.', "_preprocessing" ) return data["data"] ``` -------------------------------- ### Pre/Post-processor Return Value Source: https://github.com/marshmallow-code/marshmallow/blob/dev/docs/upgrading.rst Marshmallow 3.x requires pre/post-processors to explicitly return the processed data, even if it's None. ```python # 2.x class UserSchema(Schema): name = fields.Str() slug = fields.Str() @pre_load def slugify_name(self, in_data): # In 2.x, implicitly returning None implied that data were mutated in_data["slug"] = in_data["slug"].lower().strip().replace(" ", "-") # 3.x class UserSchema(Schema): name = fields.Str() slug = fields.Str() @pre_load def slugify_name(self, in_data, **kwargs): # In 3.x, always return the processed data in_data["slug"] = in_data["slug"].lower().strip().replace(" ", "-") return in_data ```