Skip to content

HybridModel

A Pydantic model with built-in Marshmallow support.

Class

HybridModel

Bases: BaseModel

A Pydantic model that can also work as a Marshmallow schema.

This provides a single class that gives you both Pydantic model capabilities AND Marshmallow schema functionality.

Instance Caching

ma_load() / ma_dump() cache a default schema instance for performance. Schemas with hooks (pre_load, post_load, @validates, @validates_schema, pre_dump, post_dump) always get a fresh instance to prevent leaked mutable state. The cache is protected by an RLock.

Example

class User(HybridModel): name: str email: EmailStr age: int = Field(ge=0)

Use as Pydantic model

user = User(name="Alice", email="alice@example.com", age=30)

Use for Marshmallow-style loading

user = User.ma_load({"name": "Alice", "email": "alice@example.com", "age": 30})

Get the Marshmallow schema

schema = User.marshmallow_schema()

marshmallow_schema classmethod

marshmallow_schema() -> type[PydanticSchema[Any]]

Get or create the Marshmallow schema for this model (thread-safe).

ma_load classmethod

ma_load(data: dict[str, Any], **kwargs: Any) -> HybridModel

Load data using the Marshmallow schema.

ma_loads classmethod

ma_loads(json_str: str, **kwargs: Any) -> HybridModel

Load data from a JSON string using the Marshmallow schema.

ma_dump

ma_dump(**kwargs: Any) -> dict[str, Any]

Dump this instance using the Marshmallow schema.

ma_dumps

ma_dumps(**kwargs: Any) -> str

Dump this instance to a JSON string using the Marshmallow schema.

Usage

Basic Usage

from pydantic_marshmallow import HybridModel
from pydantic import Field

class User(HybridModel):
    name: str
    email: str
    age: int = Field(ge=0)

# Use as a Pydantic model
user = User(name="Alice", email="alice@example.com", age=30)
print(user.model_dump())  # Pydantic method

# Use Marshmallow methods
data = user.ma_dump()  # Marshmallow serialization
json_str = user.ma_dumps()  # Marshmallow JSON serialization

# Load via Marshmallow
user = User.ma_load({"name": "Bob", "email": "bob@example.com", "age": 25})
user = User.ma_loads('{"name": "Charlie", "email": "c@example.com", "age": 35}')

Getting the Schema Class

For ecosystem integration:

# Get the Marshmallow schema class
UserSchema = User.marshmallow_schema()

# Use with webargs
@use_args(UserSchema(), location="json")
def create_user(user):
    pass

# Use with apispec
spec.components.schema("User", schema=UserSchema)

Validation

HybridModel uses Pydantic's strict behavior by default:

class StrictUser(HybridModel):
    name: str
    age: int

# Marshmallow load uses Pydantic validation
try:
    user = StrictUser.ma_load({"name": "", "age": -5})
except ValidationError as e:
    print(e.messages)

When to Use HybridModel

Use HybridModel when you need:

  • Both Pydantic and Marshmallow APIs on the same class
  • A drop-in replacement that works with existing Pydantic code
  • Simple cases without custom schema configuration

Use PydanticSchema when you need:

  • Custom hooks (@pre_load, @post_load, etc.)
  • Custom validators on the schema
  • Field filtering (only, exclude, load_only, dump_only)
  • Full control over schema behavior

Performance

Instance Caching

HybridModel caches default schema instances for hookless schemas, avoiding the overhead of creating a new schema object on every ma_load() / ma_dump() call.

  • Hookless schemas: Cached and reused (thread-safe via RLock)
  • Schemas with hooks: Fresh instance every call to prevent mutable state leaks
  • Passing **kwargs to any ma_load* / ma_dump* method always creates a fresh instance

Thread Safety

All ma_load(), ma_loads(), ma_dump(), and ma_dumps() methods are safe to call from multiple threads concurrently.