JsonComparator (json_comparator v1.0.4)

View Source

Provides functionality for comparing JSON structures with configurable comparison options.

JsonComparator enables deep comparison of complex data structures like those returned from JSON parsing, with support for nested maps, lists, DateTime objects, and structs.

## Key Features

  • Deep comparison of nested structures
  • Flexible list comparison (ordered or unordered)
  • DateTime comparison with configurable precision
  • Struct comparison support
  • Custom error messages
  • Detailed path reporting for differences
  • Comprehensive difference collection with deep_compare option

## Usage

Basic comparison (returns :ok or a single error):

  JsonComparator.compare(json1, json2, options)

Collect all differences between structures:

  JsonComparator.compare(json1, json2, deep_compare: true)

See compare/3 for more details and examples.

Summary

Functions

Compares two JSON structures for equality with configurable options.

Functions

compare(json1, json2, opts \\ [])

Compares two JSON structures for equality with configurable options.

This function performs a deep comparison of two JSON structures, supporting various data types including maps, lists, DateTime objects, and structs. It provides configurable behavior for list comparison and DateTime precision.

By default, this function stops and returns on the first difference found. Use the deep_compare: true option to collect all differences.

Parameters

  • json1 - First JSON structure to compare
  • json2 - Second JSON structure to compare
  • opts - Optional keyword list of comparison options:
    • :strict_list_order - When true, lists must have identical order to be considered equal. Defaults to false
    • :truncate_datetime_microseconds - When true, DateTime comparisons ignore microseconds. Defaults to true
    • :error_message - Custom error message template to use when differences are found. The string %{path} will be replaced with the path where the difference was found. Defaults to "Submitted JSONs do not match: %{path}"
    • :deep_compare - When true, collects all differences instead of stopping at the first one. Defaults to false. When true, returns {:error, differences} where differences is a list of {path, details} tuples.

Returns

  • :ok - When the structures are equal according to the comparison rules
  • {:error, message} - When differences are found and deep_compare: false, where message is a string indicating the path where the first difference was encountered
  • {:error, differences} - When differences are found and deep_compare: true, where differences is a list of tuples containing path and details about each difference

Examples

# Basic comparison (stops at first difference)
iex> JsonComparator.compare(%{a: 1, b: 2}, %{a: 1, b: 2})
:ok

iex> JsonComparator.compare(%{a: 1, b: 2}, %{a: 1, b: 3})
{:error, "Submitted JSONs do not match: b"}

# Unordered list comparison (default behavior)
iex> JsonComparator.compare([1, 2, 3], [3, 2, 1])
:ok

# Ordered list comparison
iex> JsonComparator.compare([1, 2, 3], [1, 2, 3], strict_list_order: true)
:ok

# Custom error message
iex> JsonComparator.compare(%{a: 1}, %{a: 2}, error_message: "Values differ at: %{path}")
{:error, "Values differ at: a"}

# Deep comparison (collect all differences)
iex> map1 = %{a: 1, b: 2, c: 3, d: %{e: 4, f: 5}}
iex> map2 = %{a: 1, b: 7, d: %{e: 9, g: 8}, h: 10}
iex> {:error, differences} = JsonComparator.compare(map1, map2, deep_compare: true)
iex> length(differences)
6

# Processing all differences
iex> map1 = %{a: 1, b: 2, c: 3}
iex> map2 = %{a: 1, b: 5}
iex> {:error, _diffs} = JsonComparator.compare(map1, map2, deep_compare: true)
{:error,
[
  {"c", %{type: :missing_key, actual: nil, expected: 3}},
  {"b", %{type: :value_mismatch, actual: 5, expected: 2}}
]}