0
# Type Handling
1
2
Functions for serializing complex Python types to JSON-compatible formats. The defaults module provides extensible type conversion system used by JSON formatters to handle non-standard Python objects.
3
4
## Core Imports
5
6
```python
7
import pythonjsonlogger.defaults as defaults
8
```
9
10
For type checking:
11
12
```python
13
from typing import Any, TypeGuard
14
from types import TracebackType
15
import datetime
16
import enum
17
import uuid
18
```
19
20
## Capabilities
21
22
### Universal Type Handling
23
24
Functions that handle any object type as a fallback.
25
26
```python { .api }
27
def unknown_default(obj: Any) -> str:
28
"""
29
Backup default function for any object type.
30
31
Attempts str() then repr(), falls back to placeholder string.
32
33
Parameters:
34
- obj: object to handle
35
36
Returns:
37
String representation or "__could_not_encode__"
38
"""
39
```
40
41
### Type Objects
42
43
Functions for handling Python type/class objects.
44
45
```python { .api }
46
def use_type_default(obj: Any) -> TypeGuard[type]:
47
"""
48
Check if object is a type/class object.
49
50
Parameters:
51
- obj: object to check
52
53
Returns:
54
True if obj is a type object
55
"""
56
57
def type_default(obj: type) -> str:
58
"""
59
Convert type object to string representation.
60
61
Parameters:
62
- obj: type object to handle
63
64
Returns:
65
Class name as string
66
"""
67
```
68
69
### Dataclass Handling
70
71
Functions for serializing dataclass instances.
72
73
```python { .api }
74
def use_dataclass_default(obj: Any) -> bool:
75
"""
76
Check if object is a dataclass instance.
77
78
Parameters:
79
- obj: object to check
80
81
Returns:
82
True if obj is a dataclass instance (not class)
83
"""
84
85
def dataclass_default(obj) -> dict[str, Any]:
86
"""
87
Convert dataclass instance to dictionary.
88
89
Parameters:
90
- obj: dataclass instance to handle
91
92
Returns:
93
Dictionary representation of dataclass fields
94
"""
95
```
96
97
### DateTime Handling
98
99
Functions for handling various datetime types.
100
101
```python { .api }
102
def use_time_default(obj: Any) -> TypeGuard[datetime.time]:
103
"""Check if object is datetime.time instance."""
104
105
def time_default(obj: datetime.time) -> str:
106
"""
107
Convert time object to ISO format string.
108
109
Parameters:
110
- obj: time object to handle
111
112
Returns:
113
ISO format time string
114
"""
115
116
def use_date_default(obj: Any) -> TypeGuard[datetime.date]:
117
"""Check if object is datetime.date instance."""
118
119
def date_default(obj: datetime.date) -> str:
120
"""
121
Convert date object to ISO format string.
122
123
Parameters:
124
- obj: date object to handle
125
126
Returns:
127
ISO format date string
128
"""
129
130
def use_datetime_default(obj: Any) -> TypeGuard[datetime.datetime]:
131
"""Check if object is datetime.datetime instance."""
132
133
def datetime_default(obj: datetime.datetime) -> str:
134
"""
135
Convert datetime object to ISO format string.
136
137
Parameters:
138
- obj: datetime object to handle
139
140
Returns:
141
ISO format datetime string
142
"""
143
144
def use_datetime_any(obj: Any) -> TypeGuard[datetime.time | datetime.date | datetime.datetime]:
145
"""Check if object is any datetime-related type."""
146
147
def datetime_any(obj: datetime.time | datetime.date | datetime.datetime) -> str:
148
"""
149
Convert any datetime-related object to ISO format string.
150
151
Parameters:
152
- obj: datetime-related object to handle
153
154
Returns:
155
ISO format string representation
156
"""
157
```
158
159
### Exception and Traceback Handling
160
161
Functions for serializing exceptions and traceback objects.
162
163
```python { .api }
164
def use_exception_default(obj: Any) -> TypeGuard[BaseException]:
165
"""
166
Check if object is an exception instance.
167
168
Parameters:
169
- obj: object to check
170
171
Returns:
172
True if obj is BaseException instance
173
"""
174
175
def exception_default(obj: BaseException) -> str:
176
"""
177
Convert exception to string representation.
178
179
Parameters:
180
- obj: exception instance to handle
181
182
Returns:
183
String in format "ExceptionClass: message"
184
"""
185
186
def use_traceback_default(obj: Any) -> TypeGuard[TracebackType]:
187
"""
188
Check if object is a traceback object.
189
190
Parameters:
191
- obj: object to check
192
193
Returns:
194
True if obj is traceback object
195
"""
196
197
def traceback_default(obj: TracebackType) -> str:
198
"""
199
Convert traceback to formatted string.
200
201
Parameters:
202
- obj: traceback object to handle
203
204
Returns:
205
Formatted traceback string
206
"""
207
```
208
209
### Enum Handling
210
211
Functions for serializing enum objects and classes.
212
213
```python { .api }
214
def use_enum_default(obj: Any) -> TypeGuard[enum.Enum | enum.EnumMeta]:
215
"""
216
Check if object is enum instance or enum class.
217
218
Parameters:
219
- obj: object to check
220
221
Returns:
222
True if obj is enum instance or enum class
223
"""
224
225
def enum_default(obj: enum.Enum | enum.EnumMeta) -> Any | list[Any]:
226
"""
227
Convert enum to value representation.
228
229
For enum instances returns the value.
230
For enum classes returns list of all values.
231
232
Parameters:
233
- obj: enum instance or class to handle
234
235
Returns:
236
Enum value or list of enum values
237
"""
238
```
239
240
### UUID Handling
241
242
Functions for serializing UUID objects.
243
244
```python { .api }
245
def use_uuid_default(obj: Any) -> TypeGuard[uuid.UUID]:
246
"""
247
Check if object is UUID instance.
248
249
Parameters:
250
- obj: object to check
251
252
Returns:
253
True if obj is UUID instance
254
"""
255
256
def uuid_default(obj: uuid.UUID) -> str:
257
"""
258
Convert UUID to hyphenated string format.
259
260
Parameters:
261
- obj: UUID object to handle
262
263
Returns:
264
UUID string in hyphenated format
265
"""
266
```
267
268
### Bytes Handling
269
270
Functions for serializing bytes and bytearray objects.
271
272
```python { .api }
273
def use_bytes_default(obj: Any) -> TypeGuard[bytes | bytearray]:
274
"""
275
Check if object is bytes or bytearray.
276
277
Parameters:
278
- obj: object to check
279
280
Returns:
281
True if obj is bytes or bytearray
282
"""
283
284
def bytes_default(obj: bytes | bytearray, url_safe: bool = True) -> str:
285
"""
286
Convert bytes to base64 string representation.
287
288
Parameters:
289
- obj: bytes or bytearray object to handle
290
- url_safe: use URL-safe base64 character set
291
292
Returns:
293
Base64 encoded string
294
"""
295
```
296
297
## Usage Examples
298
299
### Custom JSON Default Function
300
301
```python
302
from pythonjsonlogger.json import JsonFormatter
303
import pythonjsonlogger.defaults as defaults
304
import decimal
305
import pathlib
306
307
def custom_json_default(obj):
308
# Handle custom types
309
if isinstance(obj, decimal.Decimal):
310
return float(obj)
311
elif isinstance(obj, pathlib.Path):
312
return str(obj)
313
314
# Use built-in type handlers
315
if defaults.use_datetime_any(obj):
316
return defaults.datetime_any(obj)
317
elif defaults.use_dataclass_default(obj):
318
return defaults.dataclass_default(obj)
319
elif defaults.use_enum_default(obj):
320
return defaults.enum_default(obj)
321
elif defaults.use_exception_default(obj):
322
return defaults.exception_default(obj)
323
324
# Fallback
325
return defaults.unknown_default(obj)
326
327
# Use custom default function
328
formatter = JsonFormatter(
329
'%(levelname)s %(message)s',
330
json_default=custom_json_default
331
)
332
```
333
334
### Building Modular Default Functions
335
336
```python
337
import pythonjsonlogger.defaults as defaults
338
339
def build_json_default(*handlers):
340
"""Build a composite default function from multiple type handlers."""
341
def json_default(obj):
342
# Try each handler in order
343
for use_func, default_func in handlers:
344
if use_func(obj):
345
return default_func(obj)
346
# Final fallback
347
return defaults.unknown_default(obj)
348
return json_default
349
350
# Create composite handler
351
custom_default = build_json_default(
352
(defaults.use_datetime_any, defaults.datetime_any),
353
(defaults.use_dataclass_default, defaults.dataclass_default),
354
(defaults.use_enum_default, defaults.enum_default),
355
(defaults.use_exception_default, defaults.exception_default),
356
(defaults.use_uuid_default, defaults.uuid_default),
357
)
358
```
359
360
### Logging Complex Objects
361
362
```python
363
import logging
364
from pythonjsonlogger.json import JsonFormatter
365
from dataclasses import dataclass
366
from enum import Enum
367
from datetime import datetime
368
import uuid
369
370
@dataclass
371
class User:
372
id: int
373
name: str
374
email: str
375
376
class Status(Enum):
377
ACTIVE = "active"
378
INACTIVE = "inactive"
379
380
# Set up logger with JSON formatter
381
logger = logging.getLogger()
382
handler = logging.StreamHandler()
383
formatter = JsonFormatter('%(levelname)s %(message)s')
384
handler.setFormatter(formatter)
385
logger.addHandler(handler)
386
387
# Log complex objects - they'll be automatically converted
388
user = User(id=123, name="John Doe", email="john@example.com")
389
status = Status.ACTIVE
390
timestamp = datetime.now()
391
session_id = uuid.uuid4()
392
393
logger.info("User logged in", extra={
394
"user": user, # Converted to dict
395
"status": status, # Converted to "active"
396
"login_time": timestamp, # Converted to ISO string
397
"session_id": session_id # Converted to UUID string
398
})
399
```
400
401
### Custom Bytes Encoding
402
403
```python
404
from pythonjsonlogger.json import JsonFormatter
405
import pythonjsonlogger.defaults as defaults
406
407
def custom_bytes_handler(obj):
408
if defaults.use_bytes_default(obj):
409
# Use standard base64 instead of URL-safe
410
return defaults.bytes_default(obj, url_safe=False)
411
return defaults.unknown_default(obj)
412
413
formatter = JsonFormatter(
414
'%(levelname)s %(message)s',
415
json_default=custom_bytes_handler
416
)
417
418
# Log with bytes data
419
logger.info("Binary data received", extra={
420
"data": b"some binary data" # Will be base64 encoded
421
})
422
```
423
424
## Type Support Reference
425
426
### Automatically Handled Types
427
428
These types are handled by the JsonEncoder automatically:
429
430
- **datetime.datetime, datetime.date, datetime.time**: ISO format strings
431
- **BaseException and subclasses**: "ExceptionClass: message" format
432
- **TracebackType**: Formatted traceback strings
433
- **enum.Enum instances**: Their values
434
- **enum.EnumMeta classes**: List of all values
435
- **bytes, bytearray**: Base64 encoded strings
436
- **dataclass instances**: Dictionary representation
437
- **type objects**: Class names
438
- **UUID objects**: Hyphenated string format
439
440
### TypeGuard Functions
441
442
Functions starting with `use_` act as TypeGuard functions for type checking and provide type narrowing for mypy and other type checkers.
443
444
### Error Handling
445
446
All default functions are designed to never raise exceptions. The `unknown_default` function provides a safe fallback that attempts multiple conversion methods before returning a placeholder string.