Marshmallow: Easy Serialization in Python

Reading Time: 2 minutes

Introduction

Marshmallow, stylized as “marshmallow”, is an object-relational mapping library which is used to convert objects to and from Python data types. It is often used alongside SQLAlchemy, an ORM that maps database schemas to Python objects. Marshmallow is often used to deserialize Python dicts to SQLAlchemy models and vice versa. Let’s focus on how to use Marshmallow.

Creating Schemas

First, we need to create a schema to model the thing we want to serialize and deserialize. Let’s create a model for our schema, called Student.

import datetime as dt
class Student:
    def __init__(self, name, grade):
        self.name = name
        self.grade = grade
        self.created_at = dt.datetime.now()

Next, create the Schema using a class that maps attribute names to field objects.

from marshmallow import Schema, fields

class StudentSchema(Schema):
    name = fields.Str()
    grade = fields.Str()
    created_at = fields.DateTime()

Serializing Objects

We pass the object into the schema’s dump(s) method to serialize (object to Python type), and we use the method dumps() to return a JSON-encoded string or dump() if we want to return a dict of the object.

student = Student(name="Minh", grade="A+")
schema = StudentSchema()
result = schema.dumps(student)

# '{"name": "Minh", "grade": "A+", created_at": "2020-11-2T05:26:03.869245"}'

# We can also filter which fields we want to output
short_schema = StudentSchema(only=("name", "grade"))
short_schema.dump(user)
# {"name": "Minh", "grade": "A+"}

Deserializing Objects

Deserializing or loading, validates an Python dictionary to an application-level data structure. By default the load method will return a Python dict with the field names mapping to the value.

user_data = {
    "created_at": "2020-11-2T05:26:03.869245",
    "grade": "A+",
    "name": "Minh",
}
schema = StudentSchema()
result = schema.load(user_data)

# {'name': 'Minh',
#  'grade': 'A+',
#  'created_at': datetime.datetime(2020, 11, 2, 5, 26, 3, 869245)},

Deserializing to Objects

Result will return a Student instance if we add the @post_load declaration and the method to be ran after loading.

from marshmallow import Schema, fields, post_load

class StudentSchema(Schema):
    name = fields.Str()
    grade = fields.Str()
    created_at = fields.DateTime()

    @post_load
    def make_student(self, data, **kwargs):
        return User(**data)

user_data = {"name": "Minh", "grade": "A+"}
schema = StudentSchema()
result = schema.load(user_data)
print(result)  # => <User(name='Minh')>

Hopefully this guide has been a useful introduction to Marshmallow and object serialization in Python. Happy blogging!

Leave a Reply