I'm building and API on top of Flask using marshmallow and mongoengine. When I make a call and an ID is supposed to be serialized I receive the following error:
TypeError: ObjectId('54c117322053049ba3ef31f3') is not JSON serializable
I saw some ways with other libraries to override the way the ObjectId is treated. I haven't figured it out with Marshmallow yet, does anyone know how to do that?
My model is:
class Process(db.Document):
name = db.StringField(max_length=255, required=True, unique=True)
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
My serializer:
class ProcessSerializer(Serializer):
class Meta:
fields = ("id", "created_at", "name")
And the view:
class ProcessView(Resource):
def get(self, id):
process = Process.objects.get_or_404(id)
return ProcessSerializer(process).data
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
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 ObjectId
s.