# README
ā”ļø API tests faster than unit tests, from user traffic ā”ļø
š The must-have tool for developers in the AI-Gen era š
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:
ā¤ļø Code of Conduct
# Functions
Compare takes expected and actual JSON strings and returns the colorized differences.
CompareHeaders compares the headers of the expected and actual maps and returns the differences as colorized strings.
No description provided by the author