A high-performance Python library for comparing JSON payloads, powered by a Zig core for maximum speed.
Featurespip install fastjsondiff-zig
Or using uv:
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 .
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"
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 JSONTypeError: If inputs are not string or bytesresult = 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 filepath_b: Path to second JSON filearray_match: Array comparison strategyencoding: 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
Paths use dot notation for object keys and bracket notation for array indices:
root.name - Object keyroot.users[0] - Array elementroot.users[0].email - Nested pathBenchmarks 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 |
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}")
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))
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")
MIT
ContributingContributions are welcome! Please feel free to submit a Pull Request.
git checkout -b feature/amazing-feature)pytest tests/)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | fstache: Fast, Typed, Mustache Renderer | 0 | 10 | 28-07-2026 |
| 2 | chunkhound - Local first codebase intelligence | 0 | 10 | 24-01-2026 |
| 3 | djangofmt - A fast, HTML aware, Django template formatter, written in Rust | 0 | 10 | 21-02-2026 |
| 4 | django-query-doctor: Diagnose Slow Django Queries | 0 | 30 | 02-08-2026 |
| 5 | cinderx: High-Performance Python Runtime Extensions | 0 | 30 | 12-03-2026 |
| 6 | LLMRouter - Library for LLM Routing | 0 | 10 | 08-02-2026 |
| 7 | django-deadcode - dead code analysis tool | 0 | 26.67 | 08-02-2026 |
| 8 | sentrysearch - Semantic search over videos | 0 | 10 | 26-04-2026 |
| 9 | vresto: Interface for Copernicus Sentinel Data | 0 | 10 | 10-01-2026 |
| 10 | bedivierre/text-parser | 0 | 35 | 03-08-2026 |