Skip to main content

JCS - JSON Canonicalization for Python 3

Tests

This is a Python 3 package for a JCS (RFC 8785) compliant JSON canonicalization.

The main author of this code is Anders Rundgren. The original source code is at cyberphone/json-canonicalization including comprehensive test data.

Installation

$ pip install jcs

Using JCS

import jcs
data = jcs.canonicalize({"tag": 4})

Numbers

JCS serializes every JSON number as an IEEE 754 double precision value (RFC 8785, section 3.1). Python float values are doubles already and are serialized as is. Python int values have arbitrary precision, so canonicalize accepts an integer only if a double represents it exactly and its canonical form reads back as the same integer. It raises a ValueError for any other integer, instead of silently rounding it:

>>> jcs.canonicalize({"id": 2**53 + 1})
Traceback (most recent call last):
  ...
ValueError: Integer 9007199254740993 is not exactly representable in canonical JSON ...

Silent rounding would let different values produce identical canonical bytes, so a signature or hash over one value would also match the other. An accepted integer equals its double, so no other integer or float shares its canonical bytes, and json.loads reads them back as the same integer.

Keep in mind:

  • Canonical JSON writes the shortest digits of the nearest double. 2**60 is an exact double, but it serializes as 1152921504606847000, a different integer, so canonicalize(2**60) raises. canonicalize(1152921504606847000) raises too, because a double cannot represent it.
  • From 1e21 on, numbers are written with an exponent (10**21 becomes 1e+21) and json.loads reads them as float, so every integer that a double represents exactly is accepted.
  • For signed or hashed data, keep integers within the I-JSON safe range of ±(2**53 - 1) (RFC 7493, section 2.2) and use strings for large identifiers, counters, or amounts.
  • Canonical JSON from JavaScript and other double based implementations can contain integers like 1152921504606847000, which json.loads reads as integers that a double cannot represent. To canonicalize such text the way those implementations do, and the way jcs 0.2 did, parse integers as floats: jcs.canonicalize(json.loads(text, parse_int=float)).

The integer check is an addition to the original reference code. The serialization of all accepted values is unchanged.

Development

uv sync                          # Install dev dependencies
uv run prek install              # Install git hooks (quality gates on commit, tests on push)
uv run prek run --all-files      # Run all quality gates manually
uv run pytest --cov=jcs          # Run tests with coverage floor

Releasing

  1. Set the version in pyproject.toml and jcs/__init__.py and date the CHANGELOG entry
  2. Commit, then push a matching tag: git tag v0.3.0 && git push origin v0.3.0

The release workflow runs the quality gates and tests, checks that the tag matches the package version, builds, and publishes to PyPI via trusted publishing with attestations.

Metadata

Release files for jcs 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jcs 0.3.0
File Size Uploaded Provenance Actions
jcs-0.3.0.tar.gz 14.3 kB With provenance Details for jcs-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for jcs 0.3.0
File Interpreter ABI Platform Actions
jcs-0.3.0-py3-none-any.whl Python 3 none any Details for jcs-0.3.0-py3-none-any.whl

Total release size: 30.1 kB

Release files / jcs-0.3.0.tar.gz

Download URL jcs-0.3.0.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
92fecdd084a3e2cf896d11fdd5e2c52b6b86996061a3455fb3a4885cf651c6d6
BLAKE2b-256 checksum
How to use checksums
33c96dc379416691ab9b576b5fd88f14ddb4900376566350a6a1c2e55238d983
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Release files / jcs-0.3.0-py3-none-any.whl

Download URL jcs-0.3.0-py3-none-any.whl
Size 15.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c8e0113e717873f22ea7090cf877eed45a8715997eedc60c18ff789a3e89106d
BLAKE2b-256 checksum
How to use checksums
525be767349db2c71dff47d3692c30d780443ba5dfb844b626ef6fd54debc817
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Security for jcs 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for jcs-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page