Skip to content

Latest commit

 

History

70 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sdiff-rs

CI License: MIT MSRV

Semantic diff tool for JSON, YAML, and TOML. Compares structured data and shows only meaningful changes, ignoring formatting, whitespace, and key ordering.

Example

$ sdiff-rs old.json new.json
• age: 30 → 31

Summary: 1 modified

Where traditional diff would show every line changed due to reformatting, SDIFF shows only the actual semantic change.

Installation

cargo install sdiff-rs

Usage

# Basic usage
sdiff-rs old.json new.json              # Compare files
sdiff-rs config.json config.yaml        # Mixed formats supported
sdiff-rs Cargo.toml Cargo.toml.bak      # TOML support

# Stdin support
cat file.json | sdiff-rs - other.json --input-format=json
curl -s api/config | sdiff-rs - local.json --input-format=json

# Output formats
sdiff-rs old.json new.json --format=json    # JSON output for scripting
sdiff-rs old.json new.json --format=plain   # Plain text (no colors)
sdiff-rs old.json new.json --quiet          # Suppress summary

# Path filtering
sdiff-rs old.json new.json --ignore "metadata.timestamp"   # Ignore specific paths
sdiff-rs old.json new.json --ignore "**.version"           # Ignore version at any depth
sdiff-rs old.json new.json --only "spec.**"                # Show only spec changes

# Array comparison strategies
sdiff-rs old.json new.json --array-strategy=positional  # Compare by index (default)
sdiff-rs old.json new.json --array-strategy=lcs         # Detect insertions/deletions

Run sdiff-rs --help for all options.

Array Diff Strategies

Positional (default): Compares arrays element-by-element by index. Fast but shows misleading changes when elements are inserted.

LCS: Detects true insertions and deletions. Better for arrays where elements may be added or removed in the middle.

# Example: [1, 2, 3] → [1, 4, 2, 3]
$ sdiff-rs old.json new.json --array-strategy=positional
• [1]: 2 → 4
• [2]: 3 → 2
+ [3]: 3
Summary: 1 added, 2 modified

$ sdiff-rs old.json new.json --array-strategy=lcs
+ [1]: 4
Summary: 1 added

Path Filtering

Filter diff output using glob-style patterns:

  • foo.bar - exact path match
  • * - matches any single path segment
  • ** - matches any number of path segments
sdiff-rs old.json new.json --ignore "**.timestamp"     # Ignore all timestamp fields
sdiff-rs old.json new.json --only "spec.**"            # Only show spec changes
sdiff-rs old.json new.json --only "data.*" --ignore "data.internal"

Git

Use sdiff-rs as a git difftool for structured data files:

# Install sdiff-rs as a git difftool
sdiff-rs --git-install

# Use with git
git difftool -t sdiff-rs HEAD~1 -- config.json
git difftool -t sdiff-rs main feature -- settings.yaml

# Check config status
sdiff-rs --git-status

For automatic usage with specific file types, add to .gitattributes:

Exit Codes

  • 0: No changes (files are semantically identical)
  • 1: Changes found
  • 2: Error

Library

use sdiff_rs::{parse_file, compute_diff, format_diff, DiffConfig, OutputFormat, OutputOptions};
use std::path::Path;

let old = parse_file(Path::new("old.json"))?;
let new = parse_file(Path::new("new.json"))?;
let diff = compute_diff(&old, &new, &DiffConfig::default());
let output = format_diff(&diff, &OutputFormat::Terminal, &OutputOptions::default())?;
println!("{}", output);

Parsing from stdin or strings

use sdiff_rs::{parse_content, parse_stdin, FormatHint};

// Parse from string with format hint
let node = parse_content(r#"{"key": "value"}"#, FormatHint::Json, "input")?;

// Parse from stdin
let node = parse_stdin(FormatHint::Auto)?;

Path filtering

use sdiff_rs::{compute_diff, DiffConfig};
use sdiff_rs::filter::{filter_diff, FilterConfig};

let diff = compute_diff(&old, &new, &DiffConfig::default());

let filter = FilterConfig::new()
    .ignore("metadata.**")
    .only("spec.**");
let filtered = filter_diff(&diff, &filter);

LCS array diffing

use sdiff_rs::{compute_diff, DiffConfig, ArrayDiffStrategy};

let config = DiffConfig {
    array_diff_strategy: ArrayDiffStrategy::Lcs,
    ..Default::default()
};
let diff = compute_diff(&old, &new, &config);

License

MIT

About

Performant semantic diff tool for structured data files like JSON, YAML and TOML, written in Rust. Supports integration with Git's native diff tool.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages