Canonical JSON is a Python library designed to produce a deterministic, byte-for-byte consistent JSON serialization of Python data structures. This is crucial for applications requiring cryptographic hashing or signatures where the exact byte representation of JSON data must be consistent across different environments and executions. The library is currently at version 2.0.0 and maintains an active development and release cadence.
pip install canonicaljsonVerified import paths — ran on the pinned version, not inferred.
Demonstrates basic usage of `encode_canonical_json` and how to register a preserialization callback for custom Python objects, a feature introduced in version 2.0.0 to handle types not natively supported by standard JSON serialization. Keys in objects are sorted, and whitespace is removed for canonical form.
Remove any calls to `canonicaljson.set_json_library()`. Ensure your environment and data are compatible with the standard `json` module. If you relied on `simplejson`-specific behaviors, you may need to adjust your data or provide custom serialization hooks.
For `frozendict` or any other custom types, use `canonicaljson.register_preserialisation_callback(YourType, your_serializer_function)` to define how these objects should be serialized into a JSON-encodable structure. Alternatively, convert `frozendict` instances to standard `dict`s before encoding.
Before passing data to `encode_canonical_json`, ensure all `float('inf')`, `float('-inf')`, and `float('nan')` values are converted to `null` or a string representation (e.g., `"Infinity"`) that your consuming applications can interpret. The library focuses on canonical representation of *valid* JSON.For critical cryptographic applications, consider representing high-precision numbers or very large integers as strings within your JSON data to avoid potential floating-point representation issues. Define a clear convention for such string representations.
For `canonicaljson >= 2.0.0`, register a preserialization callback: `from canonicaljson import register_preserialisation_callback; register_preserialisation_callback(frozendict, lambda obj: dict(obj))`. Alternatively, manually convert `frozendict` to `dict` before encoding.
Define and register a `preserialisation_callback` for your custom type: `from canonicaljson import register_preserialisation_callback; class MyCustomClass: ...; def my_serializer(obj: MyCustomClass) -> dict: return {'_type': 'MyCustomClass', 'value': obj.some_attribute}; register_preserialisation_callback(MyCustomClass, my_serializer)`.Before passing your data to `canonicaljson.encode_canonical_json()`, replace these special float values with JSON-compatible alternatives, such as `None` (which serializes to `null`), or a descriptive string (e.g., `"Infinity"`, `"NaN"`). Example: `data = {k: None if isinstance(v, float) and (v == float('inf') or v == float('-inf') or v != v) else v for k, v in data.items()}`.No dependency data recorded yet.