Help us shape the future of Go! Take the 2026 Go Developer Survey

comparejson

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: MIT Imports: 6 Imported by: 0

README

compare-json-go

Go port of compare-json — structured JSON comparison: find what changed between two JSON values, with control over how keys, values, and arrays are matched.

Online playground: comparejson.com

Why

Most JSON diff tools either output unstructured text or hide the parts that matter (where a key was added, whether a type changed, whether two arrays differ in order or in content). compare-json-go returns a structured list of differences — every entry carries a path, the side it belongs to (base / contrast / both), and the kind of change (added, deleted, typeChanged, valueChanged) — so you can render, filter, or program against it.

Features

  • Deep comparison of objects, arrays, and primitives.
  • Three array comparison strategies: byIndex (default), lcs (minimal diff via Longest Common Subsequence), and unordered (multiset match).
  • Case-insensitive key and/or value matching.
  • Numeric-string equality — optionally treat "1" and 1 as equal.
  • Path tracking with both segment-array and dot-notation forms.
  • Zero external dependencies — the library and CLI use only the Go standard library.
  • CLI with table or JSON output, reading from inline strings or files.

Installation

go get github.com/unitstack/compare-json-go

Quick Start

Library
package main

import (
	"encoding/json"
	"fmt"

	comparejson "github.com/unitstack/compare-json-go"
)

func main() {
	var base, contrast interface{}
	json.Unmarshal([]byte(`{"name":"Alice","age":30}`), &base)
	json.Unmarshal([]byte(`{"name":"Bob","age":"30","email":"bob@test.com"}`), &contrast)

	diffs := comparejson.CompareJSON(base, contrast, &comparejson.CompareOptions{
		ArrayCompareMethod: comparejson.ArrayCompareByIndex, // or ArrayCompareLCS, ArrayCompareUnordered
	})
	for _, d := range diffs {
		fmt.Println(d.PathString, d.PathBelongsTo, d.DiffType)
	}
	// name   both     valueChanged
	// age    both     typeChanged
	// email  contrast added
}
CLI
go run ./cmd/compare-json base.json contrast.json
┌──────────────┬──────────────┐
│ Key          │ Change Type  │
├──────────────┼──────────────┤
│ (Base) a     │ valueChanged │
│ (Base) b     │ deleted      │
│ (Contrast) c │ added        │
└──────────────┴──────────────┘
# Array strategies and case-insensitive matching
compare-json -a lcs -k -v base.json contrast.json

# Machine-readable JSON output
compare-json --json-export base.json contrast.json

# Write the report to a file
compare-json -o diff.txt base.json contrast.json

Note: with the stdlib flag package, flags must come before the positional arguments.

Options

Flag Description
-a, --array-compare-method Array comparison strategy: byIndex (default), lcs, unordered
-k, --key-case-insensitive Compare object keys case-insensitively
-v, --value-case-insensitive Compare string values case-insensitively
--numeric-string-equals-number Treat numeric strings as equal to numbers
-j, --json-export Output the differences as JSON
-o, --output <file> Write output to a file instead of stdout

Differences from the TypeScript reference

This port intentionally uses native Go semantics instead of replicating JavaScript quirks. See COMPATIBILITY.md for the full policy. In short:

  • Numeric strings are parsed with strconv.ParseFloat (no JS Number() quirks like "" → 0, whitespace trimming, or hex).
  • Object keys are compared in lexicographic order (Go maps have no insertion order), so difference entries may be ordered differently than the TS output; content is the same.
  • Key existence checks look at own keys only (the TS reference's in-operator prototype-chain behavior is a bug and is not reproduced).
  • JSON is decoded into float64, so integers beyond 2^53 lose precision (same as JS).

Development

# build
go build ./...

# run unit tests and CLI end-to-end tests
go test ./...

The repo layout:

├── compare.go, object.go, array.go, types.go, utils.go   # library (package comparejson)
├── cmd/compare-json/                                     # CLI
│   ├── main.go
│   └── main_test.go                                      # CLI e2e tests (builds the real binary)
└── example/                                              # runnable demo

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ArrayCompareMethod

type ArrayCompareMethod string
const (
	ArrayCompareByIndex   ArrayCompareMethod = "byIndex"
	ArrayCompareLCS       ArrayCompareMethod = "lcs"
	ArrayCompareUnordered ArrayCompareMethod = "unordered"
)

type CompareOptions

type CompareOptions struct {
	ArrayCompareMethod        ArrayCompareMethod
	KeyCaseInsensitive        bool
	ValueCaseInsensitive      bool
	NumericStringEqualsNumber bool
}

type DiffType

type DiffType string
const (
	DiffTypeAdded        DiffType = "added"
	DiffTypeDeleted      DiffType = "deleted"
	DiffTypeTypeChanged  DiffType = "typeChanged"
	DiffTypeValueChanged DiffType = "valueChanged"
)

type Difference

type Difference struct {
	PathSegments  []string      `json:"pathSegments"`
	PathString    string        `json:"pathString"`
	PathBelongsTo PathBelongsTo `json:"pathBelongsTo"`
	DiffType      DiffType      `json:"diffType"`
}

func CompareJSON

func CompareJSON(base, contrast interface{}, options *CompareOptions) []Difference

type PathBelongsTo

type PathBelongsTo string
const (
	PathBelongsToBase     PathBelongsTo = "base"
	PathBelongsToContrast PathBelongsTo = "contrast"
	PathBelongsToBoth     PathBelongsTo = "both"
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL