json-deep-compare
Version:
A powerful library for comparing JSON objects with support for deep comparison, regex validation, and customizable options
317 lines (243 loc) • 9.79 kB
Markdown
# JSON Deep Compare with Field Validator

[](https://github.com/ashmeetsehgal/json-deep-compare/actions/workflows/test.yml)
[](https://github.com/ashmeetsehgal/json-deep-compare/actions/workflows/coverage.yml)
[](https://github.com/ashmeetsehgal/json-deep-compare/actions/workflows/pr-validation.yml)
[](https://github.com/ashmeetsehgal/json-deep-compare/actions/workflows/npm-publish-on-merge.yml)
[](https://www.npmjs.com/package/json-deep-compare)
[](https://github.com/ashmeetsehgal/json-deep-compare/blob/main/LICENSE)
[](https://ashmeetsehgal.com)
A powerful and flexible library for comparing JSON objects with support for deep comparison, regex validation, and customizable options.
## Playground
Try before you implement! Test the library's capabilities and experiment with different comparison options using our interactive playground:
**[JSON Deep Compare Playground](https://ashmeetsehgal.com/tools/json-compare)**
The playground allows you to:
- Compare JSON objects in real-time
- Customize comparison options
- Visualize match results and differences
- Test regex validations
## Features
- **Deep Comparison**: Perform a deep comparison of JSON objects, including nested objects and arrays.
- **Advanced Type Checking**: Compare values with precise type detection, identifying specific data types (string, number, array, object, null, etc.) and providing detailed type mismatch information.
- **Key and Value Type Comparison**: Compare both keys and value types, ensuring that mismatches in types are reported.
- **Regex Checks**: Validate string values against regex patterns, with support for both exact path matching and key name matching.
- **Result Structure**: Get results in a structured format that clearly indicates matched keys and values, unmatched keys, unmatched values, and regex check results.
- **Customizable Options**: Customize the comparison behavior with options for ignoring specific keys, treating certain values as equivalent, and handling different data types.
- **TypeScript Support**: Full TypeScript type definitions included for better development experience.
- **Performance Optimized**: Designed to efficiently handle large JSON objects.
## Installation
```bash
npm install json-deep-compare
```
You can also install from GitHub Packages. See [Publishing Documentation](./docs/npm-publishing.md) for details.
## Basic Usage
```javascript
const JSONCompare = require('json-deep-compare');
// Create objects to compare
const obj1 = {
user: {
name: "Ashmeet Sehgal",
email: "ashmeet@ashmeetsehgal.com",
details: {
phone: "+91-9876543210"
}
},
products: [
{ id: "PROD-123", name: "Product 1" }
]
};
const obj2 = {
user: {
name: "Ashmeet Sehgal",
email: "contact@ashmeetsehgal.com", // Different email
details: {
phone: "+91-9876543210"
}
},
products: [
{ id: "PROD-123", name: "Product 1" }
]
};
// Create a comparator with regex checks
const comparator = new JSONCompare({
regexChecks: {
'email': /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
'phone': /\+\d{1,3}-\d{3,14}/, // Will match any key named 'phone'
'products[0].id': /^PROD-\d+$/
},
matchKeysByName: true // Enable matching by key name for regex checks
});
// Perform the comparison
const result = comparator.compareAndValidate(obj1, obj2);
console.log(result);
```
## Options
You can customize the comparison behavior with the following options:
```javascript
const options = {
// Keys to ignore during comparison
ignoredKeys: ['createdAt', 'updatedAt'],
// Values to treat as equivalent
equivalentValues: {
'booleanTypes': [true, 'true', 1],
'emptyValues': [null, undefined, '']
},
// Regex patterns for value validation
regexChecks: {
'email': /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
'user.details.phone': '\\+\\d{1,3}-\\d{3,14}', // String pattern
'products[0].id': /^PROD-\d+$/
},
// Whether to strictly compare types
strictTypes: true,
// Whether to ignore keys in obj2 that aren't in obj1
ignoreExtraKeys: false,
// Whether to match regex by key name instead of only by path
matchKeysByName: true
};
const comparator = new JSONCompare(options);
```
## Result Structure
The comparison result has the following structure:
```javascript
{
matched: {
keys: [], // Matched keys
values: [] // Matched values
},
unmatched: {
keys: [], // Keys found in one object but not the other
values: [], // Values that don't match
types: [] // Values with mismatched types
},
regexChecks: {
passed: [], // Values that passed regex validation
failed: [] // Values that failed regex validation
},
summary: {
matchPercentage: 0, // Percentage of matched elements
totalKeysCompared: 0, // Total number of keys compared
totalMatched: 0, // Total number of matched elements
totalUnmatched: 0, // Total number of unmatched elements
totalRegexChecks: 0 // Total number of regex checks performed
}
}
```
## Advanced Usage
### Matching by Key Name
With the `matchKeysByName` option set to `true`, the library will apply regex checks to all keys with matching names, not just exact paths. This is useful for validating all fields of a specific type regardless of their location in the object.
```javascript
const comparator = new JSONCompare({
regexChecks: {
'email': /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
},
matchKeysByName: true
});
// This will validate both user.email and customer.email fields
```
### Treating Values as Equivalent
You can define sets of values that should be treated as equivalent:
```javascript
const comparator = new JSONCompare({
equivalentValues: {
'booleanTypes': [true, 'true', 1],
'emptyValues': [null, undefined, '']
}
});
// true, 'true', and 1 will be considered equivalent
// null, undefined, and '' will be considered equivalent
```
### Ignoring Extra Keys
If you only care about whether obj2 contains all the keys from obj1, you can ignore extra keys:
```javascript
const comparator = new JSONCompare({
ignoreExtraKeys: true
});
// Keys in obj2 that aren't in obj1 will be ignored
```
## Type Checking
The library includes advanced type checking capabilities to identify and report the specific types of values being compared.
### Supported Types
The following types are precisely detected:
- Primitive types: `string`, `number`, `boolean`, `undefined`
- Complex types: `array`, `object`, `null`
- Special objects: `date`, `regex`
- Custom object types based on constructor name
### Type Checking Example
```javascript
const JSONCompare = require('json-deep-compare');
const obj1 = {
id: 1, // Number
name: "Product", // String
price: "19.99" // String (will be compared with a number)
};
const obj2 = {
id: "1", // String (type mismatch with obj1.id)
name: "Product", // String (matching)
price: 19.99 // Number (type mismatch with obj1.price)
};
// Create a JSONCompare instance
const compare = new JSONCompare({
strictTypes: false // Set to true to fail comparison on type mismatches
});
// Perform the comparison
const result = compare.compare(obj1, obj2);
// Check for type mismatches
if (result.unmatched.types.length > 0) {
console.log("Type mismatches found:");
result.unmatched.types.forEach(mismatch => {
console.log(`Path: ${mismatch.path}`);
console.log(`Expected type: ${mismatch.expected}, Actual type: ${mismatch.actual}`);
});
}
```
### Strict Type Checking
When `strictTypes` is set to `true`, the comparison will stop at the first type mismatch for each path:
```javascript
const strictCompare = new JSONCompare({ strictTypes: true });
const strictResult = strictCompare.compare(obj1, obj2);
```
### Type Information in Results
Type information is included in both matched and unmatched values:
```javascript
// For matched values
{
path: "name",
value: "Product",
type: "string"
}
// For unmatched values
{
path: "id",
expected: 1,
actual: "1",
expectedType: "number",
actualType: "string",
message: "Values do not match"
}
// For type mismatches
{
path: "id",
expected: "number",
actual: "string",
message: "Types do not match: expected 'number', got 'string'"
}
```
### Type-Safe Equivalence
When using equivalence rules with different types, the types are still reported correctly:
```javascript
const compare = new JSONCompare({
equivalentValues: {
'nullish': [null, undefined]
}
});
// Result will show:
// "Values considered equivalent by rule 'nullish'"
// but will still report type1: "null", type2: "undefined"
```
## License
MIT
## Support This Project
If you find this library useful for your projects, please consider supporting its development and maintenance:
- ⭐ Star the project on GitHub - It helps increase visibility
Your support helps keep this project maintained and improved with new features!