Search code examples
pythonjson-apimarshmallow

marshmallow-jsonapi: How to reuse schema but change the `type_`?


I have many endpoints but they use the same jsonapi schema.

POST /foods
{
    "data": {
        "type": "food",
        "attributes": {
            "name": "abc",
            "item": "food"
        }
    }
}
POST /chats
{
    "data": {
        "type": "food",
        "attributes": {
            "name": "bcd",
            "item": "chat"
        }
    }
}
POST /animals
{
    "data": {
        "type": "food",
        "attributes": {
            "name": "poi",
            "item": "animals"
        }
    }
}

My schema is:

import marshmallow_jsonapi as jsonapi
ItemSchema(jsonapi.Schema):
    id = jsonapi.fields.UUID(dumps_only=True)
    name = jsonapi.fields.String(required=True)
    item = jsonapi.fields.String(required=True)

    class Meta:
        type_ = "items"
        strict = True

Following the jsonapi standard, the type will need to match each endpoint (foods, chats, animals).

import marshmallow_jsonapi as jsonapi
FoodSchema(jsonapi.Schema):
    id = jsonapi.fields.UUID(dumps_only=True)
    name = jsonapi.fields.String(required=True)
    item = jsonapi.fields.String(required=True)

    class Meta:
        type_ = "foods"
        strict = True
import marshmallow_jsonapi as jsonapi
ChatSchema(jsonapi.Schema):
    id = jsonapi.fields.UUID(dumps_only=True)
    name = jsonapi.fields.String(required=True)
    item = jsonapi.fields.String(required=True)

    class Meta:
        type_ = "chats"
        strict = True
import marshmallow_jsonapi as jsonapi
AnimalSchema(jsonapi.Schema):
    id = jsonapi.fields.UUID(dumps_only=True)
    name = jsonapi.fields.String(required=True)
    item = jsonapi.fields.String(required=True)

    class Meta:
        type_ = "animals"
        strict = True

What is a way to reduce redundant code to not have a bunch of copies of the ItemSchema with only the type changed?


Solution

  • This is the Base class (BaseClass.py)

    from marshmallow_jsonapi import fields, Schema
        
    class Base(Schema):
        id = jsonapi.fields.UUID(dumps_only=True)
        name = jsonapi.fields.String(required=True)
        item = jsonapi.fields.String(required=True)
    

    You can import the Base class in other schemas

    from BaseClass import Base
    
    FoodSchema(Base):
        # add other fields if required
    
    class Meta:
        type_ = "foods"
        strict = True
    

    Other Schema you need with same fields

    from Base import Base
    
    ChatSchema(Base):
        # add other fields if required
        
    class Meta:
        type_ = "chats"
        strict = True