0
# Response Marshalling and Fields
1
2
Flask-RESTX provides a comprehensive type system for defining response schemas with automatic serialization, validation, and documentation generation. The fields system supports primitive and complex data structures with extensive configuration options for data transformation and validation.
3
4
## Capabilities
5
6
### Marshalling Functions
7
8
Core functions for data serialization using field definitions.
9
10
```python { .api }
11
def marshal(data, fields, envelope=None, skip_none=False, mask=None, ordered=False):
12
"""
13
Serialize data using field definitions.
14
15
Parameters:
16
- data: Raw data (dict, list, object) to serialize
17
- fields: Dictionary of field definitions for serialization
18
- envelope: Optional key to wrap serialized response
19
- skip_none: Whether to skip None values in output
20
- mask: Field mask for selective serialization
21
- ordered: Whether to preserve field order
22
23
Returns:
24
dict or OrderedDict: Serialized data
25
"""
26
27
def marshal_with(fields, **kwargs):
28
"""
29
Decorator for automatic response marshalling.
30
31
Parameters:
32
- fields: Field definitions or model for marshalling
33
- envelope: Optional envelope key
34
- skip_none: Skip None values
35
- mask: Field mask
36
- ordered: Preserve order
37
38
Returns:
39
Decorator function
40
"""
41
42
def marshal_with_field(field, **kwargs):
43
"""
44
Decorator for marshalling with a single field.
45
46
Parameters:
47
- field: Single field definition
48
- kwargs: Additional marshalling options
49
50
Returns:
51
Decorator function
52
"""
53
```
54
55
### Base Field Classes
56
57
Foundation classes that other fields extend.
58
59
```python { .api }
60
class Raw:
61
def __init__(
62
self,
63
default=None,
64
attribute=None,
65
title=None,
66
description=None,
67
required=False,
68
readonly=False,
69
example=None,
70
mask=None
71
):
72
"""
73
Base field class with no formatting.
74
75
Parameters:
76
- default: Default value if field is missing
77
- attribute: Source attribute name (if different from field name)
78
- title: Field title for documentation
79
- description: Field description for documentation
80
- required: Whether field is required
81
- readonly: Whether field is read-only (documentation only)
82
- example: Example value for documentation
83
- mask: Optional mask function for output transformation
84
"""
85
86
def format(self, value):
87
"""Format the field value."""
88
89
def output(self, key, obj, ordered=False):
90
"""Extract and format value from source object."""
91
92
class StringMixin:
93
"""Mixin providing string validation functionality."""
94
95
def __init__(self, **kwargs):
96
"""Additional string-specific parameters like min_length, max_length, pattern."""
97
98
class MinMaxMixin:
99
"""Mixin providing min/max validation for numeric fields."""
100
101
def __init__(self, min_val=None, max_val=None, **kwargs):
102
"""
103
Parameters:
104
- min_val: Minimum allowed value
105
- max_val: Maximum allowed value
106
"""
107
108
class NumberMixin(MinMaxMixin):
109
"""Mixin providing number-specific validation."""
110
```
111
112
### Primitive Field Types
113
114
Fields for basic data types with validation and formatting.
115
116
```python { .api }
117
class String(StringMixin, Raw):
118
def __init__(
119
self,
120
enum=None,
121
discriminator=None,
122
min_length=None,
123
max_length=None,
124
pattern=None,
125
**kwargs
126
):
127
"""
128
String field with validation.
129
130
Parameters:
131
- enum: List of allowed string values
132
- discriminator: Property name used for polymorphism
133
- min_length: Minimum string length
134
- max_length: Maximum string length
135
- pattern: Regular expression pattern
136
- kwargs: Base field parameters
137
"""
138
139
class Integer(NumberMixin, Raw):
140
def __init__(
141
self,
142
min=None,
143
max=None,
144
exclusiveMin=None,
145
exclusiveMax=None,
146
multiple=None,
147
**kwargs
148
):
149
"""
150
Integer field with range validation.
151
152
Parameters:
153
- min: Minimum value (inclusive)
154
- max: Maximum value (inclusive)
155
- exclusiveMin: Minimum value (exclusive)
156
- exclusiveMax: Maximum value (exclusive)
157
- multiple: Value must be multiple of this number
158
- kwargs: Base field parameters
159
"""
160
161
class Float(NumberMixin, Raw):
162
def __init__(
163
self,
164
min=None,
165
max=None,
166
exclusiveMin=None,
167
exclusiveMax=None,
168
multiple=None,
169
**kwargs
170
):
171
"""
172
Float field with range validation.
173
174
Parameters:
175
- min: Minimum value (inclusive)
176
- max: Maximum value (inclusive)
177
- exclusiveMin: Minimum value (exclusive)
178
- exclusiveMax: Maximum value (exclusive)
179
- multiple: Value must be multiple of this number
180
- kwargs: Base field parameters
181
"""
182
183
class Boolean(Raw):
184
def __init__(self, **kwargs):
185
"""Boolean field that converts various inputs to bool."""
186
187
class DateTime(Raw):
188
def __init__(
189
self,
190
dt_format='iso8601',
191
min=None,
192
max=None,
193
**kwargs
194
):
195
"""
196
DateTime field with format conversion.
197
198
Parameters:
199
- dt_format: Output format ('iso8601', 'rfc822', or custom format string)
200
- min: Minimum datetime
201
- max: Maximum datetime
202
- kwargs: Base field parameters
203
"""
204
205
class Date(Raw):
206
def __init__(self, min=None, max=None, **kwargs):
207
"""
208
Date field (date only, no time component).
209
210
Parameters:
211
- min: Minimum date
212
- max: Maximum date
213
- kwargs: Base field parameters
214
"""
215
216
class Arbitrary(NumberMixin, Raw):
217
def __init__(
218
self,
219
min=None,
220
max=None,
221
exclusiveMin=None,
222
exclusiveMax=None,
223
multiple=None,
224
**kwargs
225
):
226
"""
227
Field for arbitrary precision numbers (Decimal).
228
229
Parameters:
230
- min: Minimum value (inclusive)
231
- max: Maximum value (inclusive)
232
- exclusiveMin: Minimum value (exclusive)
233
- exclusiveMax: Maximum value (exclusive)
234
- multiple: Value must be multiple of this number
235
- kwargs: Base field parameters
236
"""
237
238
class Fixed(NumberMixin, Raw):
239
def __init__(
240
self,
241
decimals=5,
242
min=None,
243
max=None,
244
exclusiveMin=None,
245
exclusiveMax=None,
246
multiple=None,
247
**kwargs
248
):
249
"""
250
Fixed precision decimal field.
251
252
Parameters:
253
- decimals: Number of decimal places
254
- min: Minimum value (inclusive)
255
- max: Maximum value (inclusive)
256
- exclusiveMin: Minimum value (exclusive)
257
- exclusiveMax: Maximum value (exclusive)
258
- multiple: Value must be multiple of this number
259
- kwargs: Base field parameters
260
"""
261
```
262
263
### Complex Field Types
264
265
Fields for structured data and relationships.
266
267
```python { .api }
268
class List(Raw):
269
def __init__(
270
self,
271
cls_or_instance,
272
min_items=None,
273
max_items=None,
274
unique=None,
275
**kwargs
276
):
277
"""
278
List/array field containing other fields.
279
280
Parameters:
281
- cls_or_instance: Field type for list items
282
- min_items: Minimum number of items
283
- max_items: Maximum number of items
284
- unique: Whether items must be unique
285
- kwargs: Base field parameters
286
"""
287
288
class Nested(Raw):
289
def __init__(
290
self,
291
model,
292
allow_null=False,
293
skip_none=False,
294
as_list=False,
295
**kwargs
296
):
297
"""
298
Nested object field using other field definitions.
299
300
Parameters:
301
- model: Dictionary of nested field definitions or Model
302
- allow_null: Whether to allow null values
303
- skip_none: Whether to skip None values in nested object
304
- as_list: Whether to treat nested field as list
305
- kwargs: Base field parameters
306
"""
307
308
class Url(StringMixin, Raw):
309
def __init__(
310
self,
311
endpoint=None,
312
absolute=False,
313
scheme=None,
314
**kwargs
315
):
316
"""
317
URL field with endpoint resolution.
318
319
Parameters:
320
- endpoint: Flask endpoint name for URL generation
321
- absolute: Whether to generate absolute URLs
322
- scheme: URL scheme override
323
- kwargs: Base field parameters
324
"""
325
326
class FormattedString(StringMixin, Raw):
327
def __init__(self, src_str, **kwargs):
328
"""
329
String field with format template.
330
331
Parameters:
332
- src_str: Format string template (e.g., "Hello {name}")
333
- kwargs: Base field parameters
334
"""
335
336
class ClassName(String):
337
def __init__(self, dash=False, **kwargs):
338
"""
339
Field that outputs the class name of the object.
340
341
Parameters:
342
- dash: Whether to convert CamelCase to dash-case
343
- kwargs: String field parameters
344
"""
345
346
class Polymorph(Nested):
347
def __init__(self, mapping, **kwargs):
348
"""
349
Polymorphic field that chooses nested schema based on discriminator.
350
351
Parameters:
352
- mapping: Dictionary mapping discriminator values to schemas
353
- kwargs: Nested field parameters
354
"""
355
356
class Wildcard(Raw):
357
def __init__(self, cls_or_instance, **kwargs):
358
"""
359
Field for arbitrary key-value pairs (dictionary passthrough).
360
361
Parameters:
362
- cls_or_instance: Field class or instance for wildcard values
363
- kwargs: Base field parameters
364
"""
365
```
366
367
### Field Utility Functions
368
369
Helper functions for field operations.
370
371
```python { .api }
372
def get_value(key, obj, default=None):
373
"""
374
Extract value from object using key (string, callable, or dot notation).
375
376
Parameters:
377
- key: Key to extract (string path, callable, or integer index)
378
- obj: Source object
379
- default: Default value if key not found
380
381
Returns:
382
Extracted value or default
383
"""
384
385
def to_marshallable_type(obj):
386
"""
387
Convert object to marshallable dictionary.
388
389
Parameters:
390
- obj: Object to convert
391
392
Returns:
393
dict or original object if already marshallable
394
"""
395
396
def is_indexable_but_not_string(obj):
397
"""Check if object is indexable but not a string."""
398
399
def is_integer_indexable(obj):
400
"""Check if object supports integer indexing."""
401
```
402
403
### Marshalling Exceptions
404
405
Exception types for marshalling errors.
406
407
```python { .api }
408
class MarshallingError(RestError):
409
def __init__(self, underlying_exception):
410
"""
411
Exception raised during field marshalling.
412
413
Parameters:
414
- underlying_exception: Original exception that caused marshalling failure
415
"""
416
```
417
418
## Usage Examples
419
420
### Basic Field Usage
421
422
```python
423
from flask_restx import fields, marshal
424
425
# Define field schema
426
user_fields = {
427
'id': fields.Integer,
428
'name': fields.String(required=True),
429
'email': fields.String,
430
'active': fields.Boolean(default=True),
431
'created_at': fields.DateTime(dt_format='iso8601')
432
}
433
434
# Sample data
435
user_data = {
436
'id': 1,
437
'name': 'John Doe',
438
'email': 'john@example.com',
439
'active': True,
440
'created_at': datetime.now()
441
}
442
443
# Marshal data
444
result = marshal(user_data, user_fields)
445
```
446
447
### Advanced Field Configuration
448
449
```python
450
# Field with validation and documentation
451
price_field = fields.Float(
452
min_val=0.0,
453
max_val=10000.0,
454
description='Product price in USD',
455
example=29.99,
456
required=True
457
)
458
459
# String field with pattern validation
460
sku_field = fields.String(
461
min_length=3,
462
max_length=20,
463
pattern=r'^[A-Z0-9-]+$',
464
description='Product SKU code',
465
example='PROD-123'
466
)
467
```
468
469
### Nested Objects
470
471
```python
472
# Address schema
473
address_fields = {
474
'street': fields.String(required=True),
475
'city': fields.String(required=True),
476
'country': fields.String(required=True),
477
'postal_code': fields.String
478
}
479
480
# User schema with nested address
481
user_fields = {
482
'name': fields.String(required=True),
483
'email': fields.String,
484
'address': fields.Nested(address_fields)
485
}
486
487
user_data = {
488
'name': 'Jane Smith',
489
'email': 'jane@example.com',
490
'address': {
491
'street': '123 Main St',
492
'city': 'Anytown',
493
'country': 'USA',
494
'postal_code': '12345'
495
}
496
}
497
498
result = marshal(user_data, user_fields)
499
```
500
501
### List Fields
502
503
```python
504
# List of primitive values
505
tags_field = fields.List(fields.String)
506
507
# List of nested objects
508
comments_field = fields.List(fields.Nested({
509
'id': fields.Integer,
510
'text': fields.String,
511
'author': fields.String,
512
'created_at': fields.DateTime
513
}))
514
515
post_fields = {
516
'title': fields.String,
517
'content': fields.String,
518
'tags': tags_field,
519
'comments': comments_field
520
}
521
```
522
523
### URL Fields
524
525
```python
526
# URL field with endpoint resolution
527
user_url_field = fields.Url('user_detail', absolute=True)
528
529
# Fields referencing Flask endpoints
530
user_fields = {
531
'id': fields.Integer,
532
'name': fields.String,
533
'url': fields.Url('user_detail'), # Generates URL to user_detail endpoint
534
'avatar_url': fields.Url('user_avatar', absolute=True)
535
}
536
```
537
538
### Decorator Usage
539
540
```python
541
from flask_restx import Resource, marshal_with
542
543
class UserList(Resource):
544
@marshal_with(user_fields)
545
def get(self):
546
# Return raw data, automatic marshalling applied
547
return [
548
{'id': 1, 'name': 'John', 'email': 'john@example.com'},
549
{'id': 2, 'name': 'Jane', 'email': 'jane@example.com'}
550
]
551
552
@marshal_with(user_fields, envelope='user')
553
def post(self):
554
# Response wrapped in envelope: {'user': {...}}
555
new_user = {'id': 3, 'name': 'Bob', 'email': 'bob@example.com'}
556
return new_user, 201
557
```
558
559
### Field Masking
560
561
```python
562
# Selective field serialization using masks
563
from flask_restx import Mask
564
565
# Only include specific fields
566
mask = Mask('name,email')
567
result = marshal(user_data, user_fields, mask=mask)
568
569
# Nested field masking
570
mask = Mask('name,address{city,country}')
571
result = marshal(user_data, user_fields, mask=mask)
572
```
573
574
### Custom Field Attributes
575
576
```python
577
# Using different source attribute
578
user_fields = {
579
'id': fields.Integer,
580
'display_name': fields.String(attribute='full_name'), # Maps to full_name attribute
581
'is_admin': fields.Boolean(attribute='admin_flag')
582
}
583
584
# Custom transformation with callable
585
def format_phone(obj):
586
return f"({obj.area_code}) {obj.number}"
587
588
user_fields = {
589
'phone': fields.String(attribute=format_phone)
590
}
591
```