How can I serialize a MongoDB ObjectId with Marshmallow?

When you just pass Meta.fields to a schema, Marshmallow tries to pick a field type for each attribute. Since it doesn't know what an ObjectId is, it just passes it on to the serialized dict. When you try to dump this to JSON, it doesn't know what an ObjectId is and raises an error. To solve this, you need to tell Marshmallow what field to use for the id. A BSON ObjectId can be converted to a string, so use a String field.

from marshmallow import Schema, fields

class ProcessSchema(Schema):
    id = fields.String()

    class Meta:
        additional =  ('created_at', 'name')

You can also tell Marshmallow what field to use for the ObjectId type so that you don't have to add the field each time.

from bson import ObjectId
from marshmallow import Schema, fields

Schema.TYPE_MAPPING[ObjectId] = fields.String

You can extend the fields.Field class to create your own field. Here's how marshmallow-mongoengine (mentioned in another answer) implements this:

import bson
from marshmallow import ValidationError, fields, missing

class ObjectId(fields.Field):
    def _deserialize(self, value, attr, data):
        try:
            return bson.ObjectId(value)
        except Exception:
            raise ValidationError("invalid ObjectId `%s`" % value)

    def _serialize(self, value, attr, obj):
        if value is None:
            return missing
        return str(value)

and then:

class MySchema(Schema):
    id = ObjectId()

(I found this useful when not using MongoEngine, just using pymongo)


marshmallow-mongoengine does this:

Marshmallow-Mongoengine is about bringing together a Mongoengine Document with a Marshmallow Schema.

import marshmallow_mongoengine as ma


class ProcessSchema(ma.ModelSchema):
    class Meta:
        model = Process

It has an ObjectId field that serializes/deserializes ObjectIds.