Skip to main content

Global Serialization Configuration

Global serialization behaviors for temporal types, binary data, and special float values are defined using the CoreConfig TypedDict. This configuration is passed to SchemaSerializer or SchemaValidator during initialization to control how data is transformed, particularly when targeting JSON output.

Configuring Temporal Types

You can control how datetime, date, time, and timedelta objects are serialized by setting ser_json_temporal or ser_json_timedelta in the CoreConfig.

from datetime import datetime
from pydantic_core import SchemaSerializer, core_schema

# Configure temporal types to serialize as Unix timestamps (seconds)
config = core_schema.CoreConfig(ser_json_temporal='seconds')
s = SchemaSerializer(core_schema.datetime_schema(), config)

dt = datetime(2024, 1, 1, 0, 0, 0)
# to_python with mode='json' returns a float
assert s.to_python(dt, mode='json') == 1704067200.0
# to_json returns the byte representation
assert s.to_json(dt) == b'1704067200.0'

Temporal Options

  • ser_json_temporal: Applies to all temporal types (datetime, date, time, timedelta).
    • 'iso8601': (Default) Serializes to ISO 8601 strings.
    • 'seconds': Serializes to Unix timestamps (float).
    • 'milliseconds': Serializes to Unix timestamps in milliseconds (float).
  • ser_json_timedelta: Specific to timedelta.
    • 'iso8601': (Default) Serializes to ISO 8601 duration strings.
    • 'float': Serializes to total seconds as a float.

Note: If ser_json_temporal is set, it takes precedence over ser_json_timedelta.

Configuring Binary Data

To handle bytes or bytearray serialization, use ser_json_bytes. You should typically pair this with val_json_bytes to ensure validation can handle the same format.

from pydantic_core import SchemaSerializer, SchemaValidator, core_schema

config = core_schema.CoreConfig(ser_json_bytes='base64', val_json_bytes='base64')
schema = core_schema.bytes_schema()

# Serialization
serializer = SchemaSerializer(schema, config)
assert serializer.to_json(b'foo') == b'"Zm9v"'

# Validation (from the same format)
validator = SchemaValidator(schema, config)
assert validator.validate_json('"Zm9v"') == b'foo'

Binary Options

  • 'utf8': (Default) Attempts to decode bytes as UTF-8 strings.
  • 'base64': Encodes bytes as Base64 strings.
  • 'hex': Encodes bytes as hexadecimal strings.

Configuring Special Float Values

By default, JSON does not support NaN, Infinity, or -Infinity. You can use ser_json_inf_nan to define how these values are handled.

from pydantic_core import SchemaSerializer, core_schema

# Configure floats to use constant names instead of null
config = core_schema.CoreConfig(ser_json_inf_nan='constants')
s = SchemaSerializer(core_schema.float_schema(), config)

assert s.to_json(float('inf')) == b'Infinity'
assert s.to_json(float('nan')) == b'NaN'

Float Options

  • 'null': (Default) Serializes NaN and Infinity as null. This is the most compatible with standard JSON parsers but loses information.
  • 'constants': Serializes as Infinity, -Infinity, and NaN. Note that this is not valid standard JSON.
  • 'strings': Serializes as "Infinity", "-Infinity", and "NaN". This is valid JSON and preserves the values as strings.

Troubleshooting

Precedence of Temporal Settings

If you find that your ser_json_timedelta setting is being ignored, check if ser_json_temporal is also defined. ser_json_temporal is a "global" temporal setting that overrides the specific timedelta configuration.

JSON Compatibility

When using ser_json_inf_nan='constants' or ser_json_bytes='base64', ensure that the consumer of your JSON output supports these formats. Standard Python json.loads can handle Infinity and NaN constants by default, but many other language implementations (like browser JSON.parse()) will throw an error. Use 'strings' for floats or 'base64' for bytes if you need strict JSON compatibility.