Skip to main content

Structural similarity scoring engine for JSON-compatible data

Project description

Sembra

Structural similarity scoring for JSON-compatible data

Italian: "sembrare" — to seem, to resemble


The Problem

Existing deep comparison libraries answer only binary questions:

Library Gives you
fast-deep-equal Equal or not?
lodash.isequal Equal or not?
deep-diff What changed?
deepdiff (Python) What changed?

None answer the most natural question:

How similar are these two structures?

When schemas evolve, keys get renamed, or data comes from different sources, binary equality is useless. You need a similarity score.

The Algorithm: Sembra Similarity

Sembra computes a continuous similarity score S(a, b) ∈ [0, 1] for any two JSON-compatible values using a novel multi-phase algorithm:

Phase 1: Type-Aware Primitive Matching

  • Strings: Jaro-Winkler distance (handles typos, minor variations)
  • Numbers: Relative difference scoring
  • Booleans: Exact match (configurable partial mode)
  • Null: Always exact

Phase 2: Optimal Array Alignment

Instead of index-by-index comparison, Sembra computes a similarity matrix between all pairs of elements and finds the optimal matching using a greedy assignment algorithm. This handles:

  • Reordered elements
  • Inserted/deleted elements
  • Partially matching elements

Phase 3: Value-Guided Key Rename Detection

This is the key novelty. When object keys differ between two structures, Sembra infers renames by comparing the values at those keys:

a = {"name": "Alice", "age": 30}
b = {"fullName": "Alice", "yearsOld": 30}
# Sembra detects: name → fullName, age → yearsOld
# Score: >0.85

No other library does this.

Phase 4: Recursive Composition

All phases compose recursively — nested arrays, nested objects, and mixed structures are handled uniformly.

Performance

Operation Complexity
Identical structures (early exit) O(n)
Similar structures O(n log n)
Dissimilar structures O(n × m)

n = number of nodes in the larger structure.

Quick Start

from sembra import sembra, sembra_report, SembraConfig

# Basic similarity
score = sembra({"a": 1, "b": 2}, {"a": 1, "b": 3})
print(score)  # ~0.89

# Key rename detection
score = sembra(
    {"userName": "Alice", "userAge": 30},
    {"name": "Alice", "age": 30}
)
print(score)  # >0.8

# Reordered arrays
score = sembra([1, 2, 3], [3, 1, 2])
print(score)  # 1.0 (all elements match)

# Detailed report
report = sembra_report({"a": 1}, {"a": 2})
print(report.score)
print(report.matches)
print(f"Computed in {report.duration_ns}ns")

# Configuration
config = SembraConfig(
    string_similarity=False,
    object_key_rename=False,
    number_threshold=0.9,
)
score = sembra({"a": "hello"}, {"a": "hallo"}, config)

Configuration Reference

Option Default Description
string_similarity True Enable fuzzy string matching
string_threshold 0.6 Minimum string similarity to count as match
number_similarity True Enable fuzzy number matching
number_threshold 0.8 Minimum number similarity to count as match
boolean_partial False Allow partial boolean matching
array_matching True Enable optimal array element matching
array_match_threshold 0.4 Minimum element similarity to match
object_key_rename True Enable value-guided key rename detection
object_rename_threshold 0.65 Minimum value similarity to infer rename
max_depth 16 Maximum recursion depth
max_array_size 200 Max array size for element-by-element matching
use_cache True Cache intermediate results
early_exit True Exit early for same-reference objects
key_weight_mode 'uniform' Key importance weighting

Use Cases

  • Test assertions with tolerance for structural variation
  • Schema migration — map old API responses to new schemas
  • Data deduplication — find structurally similar records
  • Configuration comparison — detect drifted configs
  • API monitoring — alert on structural drift
  • Merge conflict resolution — find best correspondence

Comparison with Existing Libraries

Feature Sembra deepdiff fast-deep-equal deep-diff
Continuous similarity score
Key rename detection
Array alignment
Fuzzy strings
Fuzzy numbers
Binary equality
Diff script
Cross-type matching

License

MIT — see LICENSE

Author

nhemlos

Project details


Download files

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

Source Distribution

sembra-0.1.0.tar.gz (75.3 kB view details)

Uploaded Source

Built Distribution

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

sembra-0.1.0-py3-none-any.whl (8.1 kB view details)

Uploaded Python 3

File details

Details for the file sembra-0.1.0.tar.gz.

File metadata

  • Download URL: sembra-0.1.0.tar.gz
  • Upload date:
  • Size: 75.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for sembra-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e591e20bee44b732deecab9d9a73557feb0afc5ff5bcacf5278a8b51b2cfbe02
MD5 8a9b27080b8b00255305b5cf22754526
BLAKE2b-256 234089fbe31754c009e04f06b65e374b226f21d516208fb3d5bc1d102a741522

See more details on using hashes here.

File details

Details for the file sembra-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sembra-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for sembra-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4360d798dedeb8e8e454e55b6e38c7f859b6c7b0f728f424b925417cd8d04335
MD5 3380024555c71d963cf8689228815b97
BLAKE2b-256 78c6f1d86458712ace2c125583aac0a1b1937efa540925e636caaa8088884c3a

See more details on using hashes here.

Supported by

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