0
# Marshmallow Integration
1
2
Official plugin for converting marshmallow schemas to OpenAPI format with automatic field type mapping, validation constraint extraction, and schema reference management. Enables seamless integration between marshmallow serialization and OpenAPI specification generation.
3
4
## Capabilities
5
6
### MarshmallowPlugin Class
7
8
Main plugin class for marshmallow integration with automatic field-to-OpenAPI type conversion and schema processing.
9
10
```python { .api }
11
class MarshmallowPlugin(BasePlugin):
12
Converter = OpenAPIConverter # Field converter class for OpenAPI type mapping
13
Resolver = SchemaResolver # Schema resolver class for reference resolution
14
15
def __init__(
16
self,
17
schema_name_resolver: Callable[[type[Schema]], str] | None = None
18
):
19
"""
20
Initialize marshmallow plugin.
21
22
Parameters:
23
- schema_name_resolver: Function to generate schema definition names from Schema classes
24
25
The resolver receives a Schema class and returns the name used in $ref within the generated spec.
26
For circular references, this function must not return None.
27
"""
28
```
29
30
### Schema Processing
31
32
Convert marshmallow schemas to OpenAPI schema definitions with automatic field type mapping and constraint extraction.
33
34
```python { .api }
35
def schema_helper(self, name, _, schema=None, **kwargs):
36
"""
37
Convert marshmallow Schema to OpenAPI schema definition.
38
39
Parameters:
40
- name: Schema name identifier
41
- schema: Marshmallow Schema class or instance
42
- **kwargs: Additional arguments (unused)
43
44
Returns:
45
OpenAPI schema definition dictionary or None if no schema provided
46
47
The plugin automatically:
48
- Maps marshmallow field types to OpenAPI types
49
- Extracts validation constraints (min/max, required, etc.)
50
- Handles nested schemas and references
51
- Processes field metadata for OpenAPI properties
52
"""
53
```
54
55
### Component Processing
56
57
Process parameters, responses, and headers that contain marshmallow schemas.
58
59
```python { .api }
60
def parameter_helper(self, parameter, **kwargs):
61
"""
62
Process parameter definition containing marshmallow Schema.
63
64
Parameters:
65
- parameter: Parameter definition dictionary
66
- **kwargs: Additional arguments
67
68
Returns:
69
Processed parameter definition with resolved schema references
70
"""
71
72
def response_helper(self, response, **kwargs):
73
"""
74
Process response definition containing marshmallow Schema.
75
76
Parameters:
77
- response: Response definition dictionary
78
- **kwargs: Additional arguments
79
80
Returns:
81
Processed response definition with resolved schema references
82
"""
83
84
def header_helper(self, header: dict, **kwargs: Any):
85
"""
86
Process header definition containing marshmallow Schema.
87
88
Parameters:
89
- header: Header definition dictionary
90
- **kwargs: Additional arguments
91
92
Returns:
93
Processed header definition with resolved schema references
94
"""
95
```
96
97
### Operation Processing
98
99
Process operations to resolve marshmallow schemas in request/response definitions.
100
101
```python { .api }
102
def operation_helper(
103
self,
104
path: str | None = None,
105
operations: dict | None = None,
106
**kwargs: Any
107
) -> None:
108
"""
109
Process operations to resolve marshmallow schemas.
110
111
Parameters:
112
- path: API path
113
- operations: Dictionary of operations by HTTP method
114
- **kwargs: Additional arguments
115
116
Resolves schema references in operation parameters, request bodies, and responses.
117
"""
118
```
119
120
### Field Type Mapping
121
122
Customize field type mappings for OpenAPI conversion.
123
124
```python { .api }
125
def map_to_openapi_type(self, field_cls, *args):
126
"""
127
Set custom mapping for marshmallow field class to OpenAPI type.
128
129
Parameters:
130
- field_cls: Marshmallow field class to map
131
- *args: Either (type, format) pair or existing marshmallow field class
132
133
Examples:
134
- plugin.map_to_openapi_type(CustomField, 'string', 'custom-format')
135
- plugin.map_to_openapi_type(CustomField, fields.String) # Reuse String mapping
136
"""
137
```
138
139
### Default Field Type Mappings
140
141
Default marshmallow field to OpenAPI type mappings used by the plugin.
142
143
```python { .api }
144
DEFAULT_FIELD_MAPPING: dict[type, tuple[str | None, str | None]] = {
145
marshmallow.fields.Integer: ("integer", None),
146
marshmallow.fields.Number: ("number", None),
147
marshmallow.fields.Float: ("number", None),
148
marshmallow.fields.Decimal: ("number", None),
149
marshmallow.fields.String: ("string", None),
150
marshmallow.fields.Boolean: ("boolean", None),
151
marshmallow.fields.UUID: ("string", "uuid"),
152
marshmallow.fields.DateTime: ("string", "date-time"),
153
marshmallow.fields.Date: ("string", "date"),
154
marshmallow.fields.Time: ("string", None),
155
marshmallow.fields.TimeDelta: ("integer", None),
156
marshmallow.fields.Email: ("string", "email"),
157
marshmallow.fields.URL: ("string", "url"),
158
marshmallow.fields.Dict: ("object", None),
159
marshmallow.fields.Field: (None, None),
160
marshmallow.fields.Raw: (None, None),
161
marshmallow.fields.List: ("array", None),
162
marshmallow.fields.IP: ("string", "ip"),
163
marshmallow.fields.IPv4: ("string", "ipv4"),
164
marshmallow.fields.IPv6: ("string", "ipv6"),
165
}
166
```
167
168
Each mapping is a tuple of `(type, format)` where:
169
- `type`: OpenAPI data type (string, integer, number, boolean, array, object, or None)
170
- `format`: OpenAPI format specification (email, uuid, date, date-time, ipv4, ipv6, etc., or None)
171
172
## Schema Utilities
173
174
Utility functions for working with marshmallow schemas in OpenAPI context.
175
176
### Schema Resolution
177
178
```python { .api }
179
def resolve_schema_instance(
180
schema: type[Schema] | Schema | str
181
) -> Schema:
182
"""
183
Return schema instance for given schema (class, instance, or name).
184
185
Parameters:
186
- schema: Schema class, instance, or registered class name
187
188
Returns:
189
Schema instance ready for processing
190
"""
191
192
def resolve_schema_cls(
193
schema: type[Schema] | str | Schema
194
) -> type[Schema] | list[type[Schema]]:
195
"""
196
Return schema class for given schema (class, instance, or name).
197
198
Parameters:
199
- schema: Schema class, instance, or registered class name
200
201
Returns:
202
Schema class or list of classes for union types
203
"""
204
```
205
206
### Default Schema Name Resolver
207
208
```python { .api }
209
def resolver(schema: type[Schema]) -> str:
210
"""
211
Default schema name resolver that strips 'Schema' suffix from class name.
212
213
Parameters:
214
- schema: Schema class
215
216
Returns:
217
Schema name for use in OpenAPI references
218
219
Example: UserSchema -> User, PersonSchema -> Person
220
"""
221
```
222
223
### Schema Utilities
224
225
```python { .api }
226
def get_fields(
227
schema: type[Schema] | Schema,
228
*,
229
exclude_dump_only: bool = False
230
) -> dict:
231
"""
232
Get fields from marshmallow schema.
233
234
Parameters:
235
- schema: Schema class or instance
236
- exclude_dump_only: Whether to exclude dump-only fields
237
238
Returns:
239
Dictionary of field name to field instance mappings
240
"""
241
242
def make_schema_key(schema: Schema) -> tuple:
243
"""
244
Create unique key for schema instance for caching and reference tracking.
245
246
Parameters:
247
- schema: Schema instance
248
249
Returns:
250
Tuple representing unique schema key
251
"""
252
253
def get_unique_schema_name(components: Components, name: str, counter: int = 0) -> str:
254
"""
255
Generate unique schema name when conflicts occur.
256
257
Parameters:
258
- components: Components instance from APISpec
259
- name: Base name to make unique
260
- counter: Recursion counter for numbering
261
262
Returns:
263
Unique schema name not already in components.schemas
264
265
Automatically appends numbers when name conflicts occur.
266
"""
267
```
268
269
## Constants
270
271
Schema processing constants and modifiers.
272
273
```python { .api }
274
MODIFIERS: list[str] # ['only', 'exclude', 'load_only', 'dump_only', 'partial']
275
```
276
277
## Usage Examples
278
279
### Basic Integration
280
281
```python
282
from apispec import APISpec
283
from apispec.ext.marshmallow import MarshmallowPlugin
284
from marshmallow import Schema, fields
285
286
# Create spec with marshmallow plugin
287
spec = APISpec(
288
title="Pet Store API",
289
version="1.0.0",
290
openapi_version="3.0.2",
291
plugins=[MarshmallowPlugin()]
292
)
293
294
# Define marshmallow schemas
295
class UserSchema(Schema):
296
id = fields.Int(dump_only=True)
297
username = fields.Str(required=True, validate=lambda x: len(x) >= 3)
298
email = fields.Email(required=True)
299
created_at = fields.DateTime(dump_only=True)
300
is_active = fields.Bool(load_default=True)
301
302
# Register schema - plugin automatically converts to OpenAPI
303
spec.components.schema("User", schema=UserSchema)
304
```
305
306
### Custom Schema Name Resolution
307
308
```python
309
from apispec.ext.marshmallow.common import resolve_schema_cls
310
311
def custom_schema_resolver(schema):
312
"""Custom schema name resolver."""
313
schema_cls = resolve_schema_cls(schema)
314
name = schema_cls.__name__
315
316
# Custom naming logic
317
if name.endswith('Schema'):
318
name = name[:-6]
319
320
# Add version suffix for versioned schemas
321
if hasattr(schema_cls, '__version__'):
322
name += f"V{schema_cls.__version__}"
323
324
return name
325
326
# Use custom resolver
327
plugin = MarshmallowPlugin(schema_name_resolver=custom_schema_resolver)
328
spec = APISpec("API", "1.0.0", "3.0.2", plugins=[plugin])
329
```
330
331
### Advanced Field Mapping
332
333
```python
334
from marshmallow import fields
335
336
# Custom field with specific OpenAPI mapping
337
class TimestampField(fields.Integer):
338
"""Unix timestamp field."""
339
pass
340
341
# Map custom field to OpenAPI type
342
plugin.map_to_openapi_type(TimestampField, 'integer', 'int64')
343
344
# Alternatively, reuse existing field mapping
345
plugin.map_to_openapi_type(TimestampField, fields.Integer)
346
```
347
348
### Schema with Metadata
349
350
```python
351
class ProductSchema(Schema):
352
name = fields.Str(
353
required=True,
354
metadata={
355
"description": "Product name",
356
"example": "Premium Widget"
357
}
358
)
359
price = fields.Decimal(
360
required=True,
361
validate=lambda x: x > 0,
362
metadata={
363
"description": "Product price in USD",
364
"example": 29.99
365
}
366
)
367
category = fields.Str(
368
metadata={
369
"description": "Product category",
370
"enum": ["electronics", "clothing", "books"]
371
}
372
)
373
374
# Metadata is automatically included in OpenAPI schema
375
spec.components.schema("Product", schema=ProductSchema)
376
```
377
378
### Using Schemas in Operations
379
380
```python
381
# Define request/response schemas
382
class CreateUserRequest(Schema):
383
username = fields.Str(required=True)
384
email = fields.Email(required=True)
385
password = fields.Str(required=True, load_only=True)
386
387
class UserResponse(Schema):
388
id = fields.Int()
389
username = fields.Str()
390
email = fields.Email()
391
created_at = fields.DateTime()
392
393
# Register schemas
394
spec.components.schema("CreateUserRequest", schema=CreateUserRequest)
395
spec.components.schema("UserResponse", schema=UserResponse)
396
397
# Use in path operations
398
spec.path("/users", operations={
399
"post": {
400
"summary": "Create new user",
401
"requestBody": {
402
"required": True,
403
"content": {
404
"application/json": {
405
"schema": {"$ref": "#/components/schemas/CreateUserRequest"}
406
}
407
}
408
},
409
"responses": {
410
"201": {
411
"description": "User created successfully",
412
"content": {
413
"application/json": {
414
"schema": {"$ref": "#/components/schemas/UserResponse"}
415
}
416
}
417
}
418
}
419
}
420
})
421
```
422
423
### Nested Schemas and References
424
425
```python
426
class AddressSchema(Schema):
427
street = fields.Str(required=True)
428
city = fields.Str(required=True)
429
state = fields.Str(required=True)
430
zip_code = fields.Str(required=True)
431
432
class UserProfileSchema(Schema):
433
id = fields.Int(dump_only=True)
434
name = fields.Str(required=True)
435
email = fields.Email(required=True)
436
address = fields.Nested(AddressSchema) # Automatically creates reference
437
addresses = fields.List(fields.Nested(AddressSchema)) # Array of references
438
439
# Plugin automatically handles nested schema references
440
spec.components.schema("UserProfile", schema=UserProfileSchema)
441
# This also registers AddressSchema automatically via nested reference
442
```