Skip to main content

fastjsondiff

A high-performance Python library for comparing JSON payloads, powered by a Zig core for maximum speed.

Features

  • Fast: Zig-powered core delivers sub-millisecond comparisons for typical payloads
  • Complete: Detects added, removed, and changed values with full path reporting
  • Deep: Handles arbitrarily nested structures (objects and arrays)
  • Scalable: Efficiently processes multi-megabyte JSON files
  • Pythonic: Clean API with iteration, filtering, and serialization support

Installation

pip install fastjsondiff-zig

Or using uv:

uv add fastjsondiff-zig

Development Installation

# Clone the repository
git clone https://github.com/adilkhash/fastjsondiff.git
cd fastjsondiff

# Build the Zig core
cd fastjsondiff/_zig
zig build
cd ../..

# Install in development mode
pip install -e .

# Or using uv
uv pip install -e .

Quick Start

import fastjsondiff

# Compare two JSON strings
result = fastjsondiff.compare(
    '{"name": "Alice", "age": 30}',
    '{"name": "Bob", "age": 30, "city": "NYC"}'
)

# Check if there are differences
if result:
    print(f"Found {len(result)} differences")

# Iterate over differences
for diff in result:
    print(f"{diff.type.value}: {diff.path}")
    print(f"  old: {diff.old_value}")
    print(f"  new: {diff.new_value}")

Output:

Found 2 differences
changed: root.name
  old: "Alice"
  new: "Bob"
added: root.city
  old: None
  new: "NYC"

API Reference

compare(a, b, *, array_match="index")

Compare two JSON payloads and return their differences.

Parameters:

  • a: First JSON input (string or bytes)
  • b: Second JSON input (string or bytes)
  • array_match: Array comparison strategy ("index" for position-based comparison)

Returns: DiffResult containing all differences found

Raises:

  • InvalidJsonError: If either input is not valid JSON
  • TypeError: If inputs are not string or bytes
result = fastjsondiff.compare('{"a": 1}', '{"a": 2}')

compare_files(path_a, path_b, *, array_match="index", encoding="utf-8")

Compare two JSON files.

Parameters:

  • path_a: Path to first JSON file
  • path_b: Path to second JSON file
  • array_match: Array comparison strategy
  • encoding: File encoding (default: utf-8)

Returns: DiffResult containing all differences found

result = fastjsondiff.compare_files("old.json", "new.json")

DiffResult

Container for comparison results.

result = fastjsondiff.compare(json_a, json_b)

# Length and boolean
len(result)      # Number of differences
bool(result)     # True if any differences exist

# Iteration
for diff in result:
    print(diff.path)

# Index access
first_diff = result[0]

# Filtering
added = result.filter(DiffType.ADDED)
removed = result.filter(DiffType.REMOVED)
changed = result.filter(DiffType.CHANGED)

# Summary
result.summary.added      # Count of added items
result.summary.removed    # Count of removed items
result.summary.changed    # Count of changed items
result.summary.total      # Total differences

# Metadata
result.metadata.paths_compared  # Number of paths visited
result.metadata.max_depth       # Maximum nesting depth
result.metadata.duration_ms     # Comparison time in milliseconds

# Serialization
result.to_dict()          # Convert to dictionary
result.to_json()          # Convert to JSON string
result.to_json(indent=2)  # Pretty-printed JSON

Difference

Represents a single difference.

diff.type       # DiffType.ADDED, DiffType.REMOVED, or DiffType.CHANGED
diff.path       # JSON path (e.g., "root.users[0].name")
diff.old_value  # Previous value (None for ADDED)
diff.new_value  # New value (None for REMOVED)
diff.to_dict()  # Serialize to dictionary

DiffType

Enum of difference types:

from fastjsondiff import DiffType

DiffType.ADDED    # Key/element exists in second input only
DiffType.REMOVED  # Key/element exists in first input only
DiffType.CHANGED  # Value differs between inputs

Path Format

Paths use dot notation for object keys and bracket notation for array indices:

  • root.name - Object key
  • root.users[0] - Array element
  • root.users[0].email - Nested path

Performance

Benchmarks on typical hardware:

Payload Size Keys Time
2 KB 100 0.2 ms
23 KB 1,000 2.4 ms
252 KB 10,000 24 ms
1.3 MB 50,000 122 ms

Examples

Detecting Configuration Changes

import fastjsondiff

old_config = '{"debug": false, "port": 8080}'
new_config = '{"debug": true, "port": 8080, "host": "0.0.0.0"}'

result = fastjsondiff.compare(old_config, new_config)

for diff in result:
    if diff.type == fastjsondiff.DiffType.CHANGED:
        print(f"Modified: {diff.path}")
    elif diff.type == fastjsondiff.DiffType.ADDED:
        print(f"New setting: {diff.path}")

Comparing API Responses

import fastjsondiff
import json

response_v1 = '{"users": [{"id": 1, "name": "Alice"}]}'
response_v2 = '{"users": [{"id": 1, "name": "Alice", "email": "alice@example.com"}]}'

result = fastjsondiff.compare(response_v1, response_v2)

if result:
    print("API response changed:")
    print(result.to_json(indent=2))

Filtering by Change Type

import fastjsondiff
from fastjsondiff import DiffType

result = fastjsondiff.compare(old_json, new_json)

# Get only added fields
new_fields = result.filter(DiffType.ADDED)
print(f"{len(new_fields)} new fields added")

# Get only removed fields
removed_fields = result.filter(DiffType.REMOVED)
print(f"{len(removed_fields)} fields removed")

Requirements

  • Python 3.10+
  • Zig 0.15.2 (for building from source)

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Run tests (pytest tests/)
  4. Commit your changes (git commit -m 'Add amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastjsondiff_zig-26.1.tar.gz (209.4 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

fastjsondiff_zig-26.1-py3-none-win_amd64.whl (158.9 kB view details)

Uploaded Python 3Windows x86-64

fastjsondiff_zig-26.1-py3-none-manylinux_2_17_x86_64.whl (199.7 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

fastjsondiff_zig-26.1-py3-none-macosx_11_0_arm64.whl (76.4 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file fastjsondiff_zig-26.1.tar.gz.

File metadata

  • Download URL: fastjsondiff_zig-26.1.tar.gz
  • Upload date:
  • Size: 209.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fastjsondiff_zig-26.1.tar.gz
Algorithm Hash digest
SHA256 3931059a8811d39a1807818f87e70266bcf48b44d065ab496ec44ed1c35bbd67
MD5 db731e6564a6475c234ab79740a411a6
BLAKE2b-256 325ee7d1eb9983820702664805a1a6fd98bf8aaae280494cbe807f6d0a581574

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastjsondiff_zig-26.1.tar.gz:

Publisher: ci.yml on adilkhash/fastjsondiff

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastjsondiff_zig-26.1-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for fastjsondiff_zig-26.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 bb78dc76ff60e8d47f0b409b866b51db0927006a16fc6845f7321227271e463e
MD5 9788e13e1a0c24624abad4406f8d3f29
BLAKE2b-256 f56220f23f6c038adbc8d67f6e7b9980a4c620bd73f579a573e5dddea1bb8a6e

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastjsondiff_zig-26.1-py3-none-win_amd64.whl:

Publisher: ci.yml on adilkhash/fastjsondiff

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastjsondiff_zig-26.1-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for fastjsondiff_zig-26.1-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 2ac0c7159e5088f7944ac4379ca9c55443a9858fa6702e886efa5be32f72c291
MD5 439202d5ddcdf7a205d3bad42e2d9903
BLAKE2b-256 9763d78f4955105f8a9e88ae9fe7ff888c28006f212f04fb1b6e3c3cdc559852

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastjsondiff_zig-26.1-py3-none-manylinux_2_17_x86_64.whl:

Publisher: ci.yml on adilkhash/fastjsondiff

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastjsondiff_zig-26.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fastjsondiff_zig-26.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a6444e37f19d377d2bd30d1ca1b9d9ad7a01fb4c3d898b07d5b5e4e5a77adcc2
MD5 e29768574de0cdb9d7dff56430cc8c15
BLAKE2b-256 b3f491887def17b4e7e5258e94c3551b877cf65950911458539da3b7e1103804

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastjsondiff_zig-26.1-py3-none-macosx_11_0_arm64.whl:

Publisher: ci.yml on adilkhash/fastjsondiff

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

26.1 This release

4 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page