colorisediff

package module
v1.0.6 Latest Latest
Warning

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

Go to latest
Published: Jun 9, 2025 License: Apache-2.0 Imports: 9 Imported by: 1

README

keploy logo

⚡️ API tests faster than unit tests, from user traffic ⚡️

🌟 The must-have tool for developers in the AI-Gen era 🌟


Keploy Twitter Help us reach 4k stars! Keploy CNCF Landscape

Slack LinkedIn YouTube Twitter

jsonDiff

jsonDiff is a Go package that allows you to compare JSON objects and return the differences as colorized strings.

Features

  • Compare two JSON objects and highlight the differences.
  • Supports comparing headers of expected and actual maps.
  • Provides colorized differences for easy visualization.

Installation

go get github.com/keploy/jsonDiff

Usage

Comparing JSON Objects

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"regexp"
	"strings"

	jsonDiff "github.com/keploy/jsonDiff"
	"github.com/olekukonko/tablewriter"
)

func main() {
	json1 := []byte("{\"animals\":[{\"name\":\"Dog\"},{\"name\":\"Cat\"},{\"name\":\"Elephant\"}]}")
	json2 := []byte("{\"animals\":[{\"name\":\"Dog\"},{\"name\":\"Cat\"},{\"apple\":\"lusiancs\"},{\"name\":\"Elephant\"}]}")

	diff, err := jsonDiff.CompareJSON(json1, json2, nil, false)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	result := expectActualTable(diff.Actual, diff.Expected, "", false)
	println(result)
}

func wrapTextWithAnsi(input string) string {
	scanner := bufio.NewScanner(strings.NewReader(input)) // Create a scanner to read the input string line by line.
	var wrappedBuilder strings.Builder                    // Builder for the resulting wrapped text.
	currentAnsiCode := ""                                 // Variable to hold the current ANSI escape sequence.
	lastAnsiCode := ""                                    // Variable to hold the last ANSI escape sequence.

	// Iterate over each line in the input string.
	for scanner.Scan() {
		line := scanner.Text() // Get the current line.

		// If there is a current ANSI code, append it to the builder.
		if currentAnsiCode != "" {
			wrappedBuilder.WriteString(currentAnsiCode)
		}

		// Find all ANSI escape sequences in the current line.
		startAnsiCodes := ansiRegex.FindAllString(line, -1)
		if len(startAnsiCodes) > 0 {
			// Update the last ANSI escape sequence to the last one found in the line.
			lastAnsiCode = startAnsiCodes[len(startAnsiCodes)-1]
		}

		// Append the current line to the builder.
		wrappedBuilder.WriteString(line)

		// Check if the current ANSI code needs to be reset or updated.
		if (currentAnsiCode != "" && !strings.HasSuffix(line, ansiResetCode)) || len(startAnsiCodes) > 0 {
			// If the current line does not end with a reset code or if there are ANSI codes, append a reset code.
			wrappedBuilder.WriteString(ansiResetCode)
			// Update the current ANSI code to the last one found in the line.
			currentAnsiCode = lastAnsiCode
		} else {
			// If no ANSI codes need to be maintained, reset the current ANSI code.
			currentAnsiCode = ""
		}

		// Append a newline character to the builder.
		wrappedBuilder.WriteString("\n")
	}

	// Return the processed string with properly wrapped ANSI escape sequences.
	return wrappedBuilder.String()
}

func expectActualTable(exp string, act string, field string, centerize bool) string {
	buf := &bytes.Buffer{}
	table := tablewriter.NewWriter(buf)

	if centerize {
		table.SetAlignment(tablewriter.ALIGN_CENTER)
	} else {
		table.SetAlignment(tablewriter.ALIGN_LEFT)
	}
	// jsonDiff.JsonDiff()
	exp = wrapTextWithAnsi(exp)
	act = wrapTextWithAnsi(act)
	table.SetHeader([]string{fmt.Sprintf("Expect %v", field), fmt.Sprintf("Actual %v", field)})
	table.SetAutoWrapText(false)
	table.SetBorder(false)
	table.SetColMinWidth(0, maxLineLength)
	table.SetColMinWidth(1, maxLineLength)
	table.Append([]string{exp, act})
	table.Render()
	return buf.String()
}

const maxLineLength = 50

var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)

var ansiResetCode = "\x1b[0m"

Comparing Headers

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"regexp"
	"strings"

	jsonDiff "github.com/keploy/jsonDiff"
	"github.com/olekukonko/tablewriter"
)

func main() {
	json1 := map[string]string{
		"Etag": "W/\"1c0-4VkjzPwyKEH0Xy9lGO28f/cyPk4\"",
		"Vary": "a",
	}
	json2 := map[string]string{
		"Etag": "W/\"1c0-8j/k9MOCbWGtKgVesjFGmY6dEAs\"",
		"Vary": "Origin",
	}
	diff := jsonDiff.CompareHeaders(json1, json2)

	result := expectActualTable(diff.Actual, diff.Expected, "", false)
	println(result)
}

func wrapTextWithAnsi(input string) string {
	scanner := bufio.NewScanner(strings.NewReader(input)) // Create a scanner to read the input string line by line.
	var wrappedBuilder strings.Builder                    // Builder for the resulting wrapped text.
	currentAnsiCode := ""                                 // Variable to hold the current ANSI escape sequence.
	lastAnsiCode := ""                                    // Variable to hold the last ANSI escape sequence.

	// Iterate over each line in the input string.
	for scanner.Scan() {
		line := scanner.Text() // Get the current line.

		// If there is a current ANSI code, append it to the builder.
		if currentAnsiCode != "" {
			wrappedBuilder.WriteString(currentAnsiCode)
		}

		// Find all ANSI escape sequences in the current line.
		startAnsiCodes := ansiRegex.FindAllString(line, -1)
		if len(startAnsiCodes) > 0 {
			// Update the last ANSI escape sequence to the last one found in the line.
			lastAnsiCode = startAnsiCodes[len(startAnsiCodes)-1]
		}

		// Append the current line to the builder.
		wrappedBuilder.WriteString(line)

		// Check if the current ANSI code needs to be reset or updated.
		if (currentAnsiCode != "" && !strings.HasSuffix(line, ansiResetCode)) || len(startAnsiCodes) > 0 {
			// If the current line does not end with a reset code or if there are ANSI codes, append a reset code.
			wrappedBuilder.WriteString(ansiResetCode)
			// Update the current ANSI code to the last one found in the line.
			currentAnsiCode = lastAnsiCode
		} else {
			// If no ANSI codes need to be maintained, reset the current ANSI code.
			currentAnsiCode = ""
		}

		// Append a newline character to the builder.
		wrappedBuilder.WriteString("\n")
	}

	// Return the processed string with properly wrapped ANSI escape sequences.
	return wrappedBuilder.String()
}

func expectActualTable(exp string, act string, field string, centerize bool) string {
	buf := &bytes.Buffer{}
	table := tablewriter.NewWriter(buf)

	if centerize {
		table.SetAlignment(tablewriter.ALIGN_CENTER)
	} else {
		table.SetAlignment(tablewriter.ALIGN_LEFT)
	}
	// jsonDiff.JsonDiff()
	exp = wrapTextWithAnsi(exp)
	act = wrapTextWithAnsi(act)
	table.SetHeader([]string{fmt.Sprintf("Expect %v", field), fmt.Sprintf("Actual %v", field)})
	table.SetAutoWrapText(false)
	table.SetBorder(false)
	table.SetColMinWidth(0, maxLineLength)
	table.SetColMinWidth(1, maxLineLength)
	table.Append([]string{exp, act})
	table.Render()
	return buf.String()
}

const maxLineLength = 50

var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)

var ansiResetCode = "\x1b[0m"

👨🏻‍💻 Let's Build Together! 👩🏻‍💻

Whether you're a newbie coder or a wizard 🧙‍♀️, your perspective is golden. Take a peek at our:

📜 Contribution Guidelines

❤️ Code of Conduct

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Diff

type Diff struct {
	Expected string
	Actual   string
}

Diff holds the colorized differences between the expected and actual JSON responses. Expected: The colorized string representing the differences in the expected JSON response. Actual: The colorized string representing the differences in the actual JSON response.

func Compare

func Compare(expectedJSON, actualJSON string) Diff

Compare takes expected and actual JSON strings and returns the colorized differences. expectedJSON: The JSON string containing the expected values. actualJSON: The JSON string containing the actual values. Returns a Diff struct containing the colorized differences for the expected and actual JSON responses.

func CompareHeaders

func CompareHeaders(expectedHeaders, actualHeaders map[string]string) Diff

CompareHeaders compares the headers of the expected and actual maps and returns the differences as colorized strings. expect: The map containing the expected header values. actual: The map containing the actual header values. Returns a ColorizedResponse containing the colorized differences for the expected and actual headers.

func CompareJSON

func CompareJSON(expectedJSON []byte, actualJSON []byte, noise map[string][]string, disableColor bool) (Diff, error)

Jump to

Keyboard shortcuts

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