Registry / serialization / canonicaljson

canonicaljson

JSON →
library2.0.0pypypi✓ verified 86d ago

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 canonicaljson
INSTALL
IMPORT
SIG · CANONICALJSON
C
canonicaljson
serializationpythonv2.0.0
Install
1.5s avg
Import
15ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v2.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.016s · 17.8MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 1.5s · import 0.014s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

encode_canonical_json
from canonicaljson import encode_canonical_json
import canonicaljson.encode_canonical_json
The primary function `encode_canonical_json` is typically imported directly from the top-level package.
register_preserialisation_callback
from canonicaljson import register_preserialisation_callback
Needed for custom type serialization in v2.0.0 and later.

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.

import canonicaljson from typing import Any, Dict data = {"b": 2, "a": 1, "nested": {"y": 2, "x": 1}, "list": [3, 1, 2]} canonical_bytes = canonicaljson.encode_canonical_json(data) print(f"Canonical JSON: {canonical_bytes.decode('utf-8')}") # Expected: {"a":1,"b":2,"list":[3,1,2],"nested":{"x":1,"y":2}} # Example for custom types (v2.0.0+) class CustomObject: def __init__(self, value): self.value = value def custom_serializer(obj: CustomObject) -> Dict[str, Any]: return {"custom_value": obj.value, "_type": "CustomObject"} canonicaljson.register_preserialisation_callback(CustomObject, custom_serializer) custom_data = {"item": CustomObject("hello")} custom_canonical_bytes = canonicaljson.encode_canonical_json(custom_data) print(f"Canonical JSON with Custom Object: {custom_canonical_bytes.decode('utf-8')}") # Expected: {"item":{"_type":"CustomObject","custom_value":"hello"}}
Debug
Known issues
breakingVersion 2.0.0 removed direct support for `simplejson` and the `set_json_library` function. The library now relies solely on the standard library's `json` module. Code that explicitly configured `simplejson` or relied on its default use will break.
fix
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.
affects: >=2.0.0
breakingVersion 2.0.0 removed built-in support for serializing `frozendict` instances directly. If your data structures included `frozendict`, they will no longer be automatically converted to canonical JSON.
fix
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.
affects: >=2.0.0
breakingVersion 1.4.0 introduced stricter compliance with RFC 7159 regarding floating-point numbers, specifically `Infinity`, `-Infinity`, and `NaN`. Previously, these might have been encoded in a non-standard way. Now, encoding objects containing these values directly will likely cause `TypeError` as they are not valid JSON numbers.
fix
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.
affects: >=1.4.0
gotchaWhile `canonicaljson` ensures consistent output, floating-point numbers in JSON are based on IEEE 754 double-precision, which can lead to precision loss for very large integers or specific decimal representations. This can potentially cause different systems to derive different canonical forms if they handle number precision differently before serialization.
fix
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.
affects: All
Errors
Common errors & fixes
TypeError: Object of type frozendict is not JSON serializable
Attempting to serialize a `frozendict` instance directly with `canonicaljson` version 2.0.0 or later, without registering a custom serialization callback. Older versions of `canonicaljson` (pre-2.0.0) might have handled it, but v2.0.0 removed this built-in support.
fix
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.
TypeError: Object of type <YourCustomType> is not JSON serializable
You are trying to serialize a custom Python object type that `canonicaljson` (and the underlying `json` module) doesn't know how to convert into a JSON primitive (like string, number, dict, list, boolean, null).
fix
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)`.
ValueError: Invalid float value for JSON encoding: Infinity
You are attempting to serialize a Python `float('inf')`, `float('-inf')`, or `float('nan')` directly into JSON. These are not valid numeric values in the JSON specification (RFC 8259), and `canonicaljson` enforces this compliance, especially since v1.4.0.
fix
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()}`.
Upgrade
Version history
2.0.0latest on PyPI · released Mar 15, 2023
Audit
Dependencies

No dependency data recorded yet.

Agent activity
12 hits · last 30 days
node
10
OpenAI (training)
1
Resources
canonicaljson — pip install canonicaljson · libregistry