A powerful and extensible data validation and comparison tool for developers and testers.
Project description
validly
Validly
A powerful and extensible data validation and comparison tool designed for developers and testers. Easily integrate into your automation projects to ensure JSON data integrity.
Features
- Deep, Recursive Comparison: Validates nested JSON structures seamlessly.
- Flexible Options: Control validation with a rich set of options for every use case.
- Order-Agnostic Lists: Intelligently compares lists of objects regardless of their order.
- Domain-Specific Validations: Built-in checks for common data formats like UUIDs, PAN, and Aadhaar numbers.
- Referencing Capabilities: Use a dynamic template to compare a field's value to another field in the
actualJSON. - Custom Validators: Extend validation logic with your own Python methods from an external file.
- Numeric Comparisons: Validate fields with operators like greater than (
gt), less than (lt), and more. - Wildcard Matching: Use placeholders to ignore values that are dynamic or unpredictable.
Installation
Validly is available on PyPI. Install it with pip:
pip install Validly
Basic Usage
Use json_difference to compare two JSON objects. It returns a list of failure messages if differences are found.
from Validly import json_difference
expected = {"id": 100, "name": "test"}
actual = {"id": 101, "name": "test"}
differences = json_difference(expected, actual)
# Output:
# ❌ Value mismatch at id: expected '100', got '101'
Advanced Usage with Options
Pass a dictionary of options to customize the validation behavior.
from Validly import json_difference
# --- Sample Data ---
expected_data = {
"user_id": "{ACTUAL_VALUE:user.id}",
"user": {
"id": 1234,
"name": "Jane Doe",
"age": 30
},
"uuid_field": "{ACTUAL_VALUE:user.uuid}",
"pan_field": "{ACTUAL_VALUE:user.pan}",
"login_count": 5
}
actual_data = {
"user_id": 1234,
"user": {
"id": 1234,
"name": "John Doe",
"age": 32,
"email": "test@example.com",
"uuid": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
"pan": "ABCDE1234F"
},
"uuid_field": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
"pan_field": "ABCDE1234F",
"login_count": 6
}
# --- Validation Options ---
# This is a sample `custom_validators.py` file with your validation logic.
# You would need to create this file in your project.
#
# custom_validators.py
# import re
# from typing import Any, Tuple
# def validate_email_format(expected: Any, actual: Any) -> Tuple[bool, str]:
# if not isinstance(actual, str): return False, "Value is not a string."
# email_pattern = re.compile(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")
# if email_pattern.match(actual): return True, ""
# return False, "Value is not a valid email format."
options = {
"wildcard_keys": ["user.name"],
"numeric_validations": {
"user.age": {"operator": "gt", "value": 30},
"login_count": {"operator": "le", "value": 5}
},
"is_uuid_keys": ["user.uuid", "uuid_field"],
"is_pan_keys": ["user.pan", "pan_field"],
"is_aadhar_keys": ["user.pan", "pan_field"],
"custom_validators": {"user.email": "validate_email_format"},
"custom_validator_path": "custom_validators.py",
"skip_keys": ["user_id"]
}
# --- Running the comparison ---
differences = json_difference(expected_data, actual_data, options=options)
# Expected differences:
# ❌ Value mismatch at user.name: expected 'Jane Doe', got 'John Doe'
# ❌ Numeric validation failed at login_count: Value is not less than or equal to 5
# ❌ Extra key in actual: user.email
Custom Validators
Create a Python file (e.g., custom_validators.py) with your custom logic. Your validator methods should accept expected and actual values and return a (bool, str) tuple.
# custom_validators.py
import re
from typing import Any, Tuple
def validate_email_format(expected: Any, actual: Any) -> Tuple[bool, str]:
# ... (code as provided) ...
Then, configure the validator in your options dictionary:
options = {
"custom_validators": {"user.email": "validate_email_format"},
"custom_validator_path": "custom_validators.py"
}
Command Line Usage
Compare two files directly from your terminal:
python -m Validly expected.json actual.json
Contributing
We welcome contributions! If you have a feature idea or find a bug, please open an issue or submit a pull request on GitHub.
License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file validly-1.0.0.tar.gz.
File metadata
- Download URL: validly-1.0.0.tar.gz
- Upload date:
- Size: 7.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f331b5941d84930cb3292c613f5fd35f0d3fdd03cd2e49e8769f4e7fb7013d0
|
|
| MD5 |
835211b85fd0fe754d24db66c5428d48
|
|
| BLAKE2b-256 |
cf705f575432f2d9627291662d649f95d61a760b267aadb4ac0a232b676add5d
|
File details
Details for the file validly-1.0.0-py3-none-any.whl.
File metadata
- Download URL: validly-1.0.0-py3-none-any.whl
- Upload date:
- Size: 7.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d64ca19b8917b3b21f4add5190a56f412db0cb7f8cb1677de3433a2af0460e4
|
|
| MD5 |
8c9e93d32f4d02bcc44c7600155a475a
|
|
| BLAKE2b-256 |
99e9d348997c8f729d0a0f27664bb3ad7f1866b3dca720dc48343dc1a2321930
|