{"id":20791432,"url":"https://github.com/keploy/jsondiff","last_synced_at":"2025-05-05T21:24:21.367Z","repository":{"id":249039870,"uuid":"828979782","full_name":"keploy/jsondiff","owner":"keploy","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-26T08:19:11.000Z","size":160,"stargazers_count":5,"open_issues_count":10,"forks_count":8,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-05-04T04:56:55.490Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/keploy.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-15T14:06:53.000Z","updated_at":"2025-04-18T08:42:23.000Z","dependencies_parsed_at":"2024-08-27T07:47:22.309Z","dependency_job_id":"b8697b81-3dc4-4def-8502-16f16fc67ceb","html_url":"https://github.com/keploy/jsondiff","commit_stats":null,"previous_names":["keploy/jsondiff"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keploy%2Fjsondiff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keploy%2Fjsondiff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keploy%2Fjsondiff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keploy%2Fjsondiff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/keploy","download_url":"https://codeload.github.com/keploy/jsondiff/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252577636,"owners_count":21770844,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T15:44:41.417Z","updated_at":"2025-05-05T21:24:21.324Z","avatar_url":"https://github.com/keploy.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg align=\"center\" src=\"https://docs.keploy.io/img/keploy-logo-dark.svg?s=200\u0026v=4\" height=\"40%\" width=\"40%\" alt=\"keploy logo\"/\u003e\n\u003c/p\u003e\n\u003ch3 align=\"center\"\u003e\n\u003cb\u003e\n⚡️ API tests faster than unit tests, from user traffic ⚡️\n\u003c/b\u003e\n\u003c/h3\u003e\n\u003cp align=\"center\"\u003e\n🌟 The must-have tool for developers in the AI-Gen era 🌟\n\u003c/p\u003e\n\n---\n\n\u003ch4 align=\"center\"\u003e\n\n\u003ca href=\"https://twitter.com/Keploy_io\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/follow-%40keployio-1DA1F2?logo=twitter\u0026style=social\" alt=\"Keploy Twitter\" /\u003e\n  \u003c/a\u003e\n\n\u003ca href=\"https://github.com/Keploy/Keploy/issues\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/stars/keploy/keploy?color=%23EAC54F\u0026logo=github\u0026label=Help us reach 4k stars! Now at:\" alt=\"Help us reach 4k stars!\" /\u003e\n  \u003c/a\u003e\n\n  \u003ca href=\"https://landscape.cncf.io/?item=app-definition-and-development--continuous-integration-delivery--keploy\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/CNCF%20Landscape-5699C6?logo=cncf\u0026style=social\" alt=\"Keploy CNCF Landscape\" /\u003e\n  \u003c/a\u003e\n\n[![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge\u0026logo=slack\u0026logoColor=white)](https://join.slack.com/t/keploy/shared_invite/zt-2dno1yetd-Ec3el~tTwHYIHgGI0jPe7A)\n[![LinkedIn](https://img.shields.io/badge/linkedin-%230077B5.svg?style=for-the-badge\u0026logo=linkedin\u0026logoColor=white)](https://www.linkedin.com/company/keploy/)\n[![YouTube](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge\u0026logo=YouTube\u0026logoColor=white)](https://www.youtube.com/channel/UC6OTg7F4o0WkmNtSoob34lg)\n[![Twitter](https://img.shields.io/badge/Twitter-%231DA1F2.svg?style=for-the-badge\u0026logo=Twitter\u0026logoColor=white)](https://twitter.com/Keployio)\n\n\u003c/h4\u003e\n\n# jsonDiff\n`jsonDiff` is a Go package that allows you to compare JSON objects and return the differences as colorized strings.\n\n## Features\n- Compare two JSON objects and highlight the differences.\n- Supports comparing headers of expected and actual maps.\n- Provides colorized differences for easy visualization.\n\n## Installation\n\n```sh\ngo get github.com/keploy/jsonDiff\n```\n\n# Usage\n\n## Comparing JSON Objects\n\n```sh\npackage main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\n\tjsonDiff \"github.com/keploy/jsonDiff\"\n\t\"github.com/olekukonko/tablewriter\"\n)\n\nfunc main() {\n\tjson1 := []byte(\"{\\\"animals\\\":[{\\\"name\\\":\\\"Dog\\\"},{\\\"name\\\":\\\"Cat\\\"},{\\\"name\\\":\\\"Elephant\\\"}]}\")\n\tjson2 := []byte(\"{\\\"animals\\\":[{\\\"name\\\":\\\"Dog\\\"},{\\\"name\\\":\\\"Cat\\\"},{\\\"apple\\\":\\\"lusiancs\\\"},{\\\"name\\\":\\\"Elephant\\\"}]}\")\n\n\tdiff, err := jsonDiff.CompareJSON(json1, json2, nil, false)\n\tif err != nil {\n\t\tfmt.Println(\"Error:\", err)\n\t\treturn\n\t}\n\tresult := expectActualTable(diff.Actual, diff.Expected, \"\", false)\n\tprintln(result)\n}\n\nfunc wrapTextWithAnsi(input string) string {\n\tscanner := bufio.NewScanner(strings.NewReader(input)) // Create a scanner to read the input string line by line.\n\tvar wrappedBuilder strings.Builder                    // Builder for the resulting wrapped text.\n\tcurrentAnsiCode := \"\"                                 // Variable to hold the current ANSI escape sequence.\n\tlastAnsiCode := \"\"                                    // Variable to hold the last ANSI escape sequence.\n\n\t// Iterate over each line in the input string.\n\tfor scanner.Scan() {\n\t\tline := scanner.Text() // Get the current line.\n\n\t\t// If there is a current ANSI code, append it to the builder.\n\t\tif currentAnsiCode != \"\" {\n\t\t\twrappedBuilder.WriteString(currentAnsiCode)\n\t\t}\n\n\t\t// Find all ANSI escape sequences in the current line.\n\t\tstartAnsiCodes := ansiRegex.FindAllString(line, -1)\n\t\tif len(startAnsiCodes) \u003e 0 {\n\t\t\t// Update the last ANSI escape sequence to the last one found in the line.\n\t\t\tlastAnsiCode = startAnsiCodes[len(startAnsiCodes)-1]\n\t\t}\n\n\t\t// Append the current line to the builder.\n\t\twrappedBuilder.WriteString(line)\n\n\t\t// Check if the current ANSI code needs to be reset or updated.\n\t\tif (currentAnsiCode != \"\" \u0026\u0026 !strings.HasSuffix(line, ansiResetCode)) || len(startAnsiCodes) \u003e 0 {\n\t\t\t// If the current line does not end with a reset code or if there are ANSI codes, append a reset code.\n\t\t\twrappedBuilder.WriteString(ansiResetCode)\n\t\t\t// Update the current ANSI code to the last one found in the line.\n\t\t\tcurrentAnsiCode = lastAnsiCode\n\t\t} else {\n\t\t\t// If no ANSI codes need to be maintained, reset the current ANSI code.\n\t\t\tcurrentAnsiCode = \"\"\n\t\t}\n\n\t\t// Append a newline character to the builder.\n\t\twrappedBuilder.WriteString(\"\\n\")\n\t}\n\n\t// Return the processed string with properly wrapped ANSI escape sequences.\n\treturn wrappedBuilder.String()\n}\n\nfunc expectActualTable(exp string, act string, field string, centerize bool) string {\n\tbuf := \u0026bytes.Buffer{}\n\ttable := tablewriter.NewWriter(buf)\n\n\tif centerize {\n\t\ttable.SetAlignment(tablewriter.ALIGN_CENTER)\n\t} else {\n\t\ttable.SetAlignment(tablewriter.ALIGN_LEFT)\n\t}\n\t// jsonDiff.JsonDiff()\n\texp = wrapTextWithAnsi(exp)\n\tact = wrapTextWithAnsi(act)\n\ttable.SetHeader([]string{fmt.Sprintf(\"Expect %v\", field), fmt.Sprintf(\"Actual %v\", field)})\n\ttable.SetAutoWrapText(false)\n\ttable.SetBorder(false)\n\ttable.SetColMinWidth(0, maxLineLength)\n\ttable.SetColMinWidth(1, maxLineLength)\n\ttable.Append([]string{exp, act})\n\ttable.Render()\n\treturn buf.String()\n}\n\nconst maxLineLength = 50\n\nvar ansiRegex = regexp.MustCompile(`\\x1b\\[[0-9;]*[a-zA-Z]`)\n\nvar ansiResetCode = \"\\x1b[0m\"\n```\n\n## Comparing Headers\n\n```sh\npackage main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\n\tjsonDiff \"github.com/keploy/jsonDiff\"\n\t\"github.com/olekukonko/tablewriter\"\n)\n\nfunc main() {\n\tjson1 := map[string]string{\n\t\t\"Etag\": \"W/\\\"1c0-4VkjzPwyKEH0Xy9lGO28f/cyPk4\\\"\",\n\t\t\"Vary\": \"a\",\n\t}\n\tjson2 := map[string]string{\n\t\t\"Etag\": \"W/\\\"1c0-8j/k9MOCbWGtKgVesjFGmY6dEAs\\\"\",\n\t\t\"Vary\": \"Origin\",\n\t}\n\tdiff := jsonDiff.CompareHeaders(json1, json2)\n\n\tresult := expectActualTable(diff.Actual, diff.Expected, \"\", false)\n\tprintln(result)\n}\n\nfunc wrapTextWithAnsi(input string) string {\n\tscanner := bufio.NewScanner(strings.NewReader(input)) // Create a scanner to read the input string line by line.\n\tvar wrappedBuilder strings.Builder                    // Builder for the resulting wrapped text.\n\tcurrentAnsiCode := \"\"                                 // Variable to hold the current ANSI escape sequence.\n\tlastAnsiCode := \"\"                                    // Variable to hold the last ANSI escape sequence.\n\n\t// Iterate over each line in the input string.\n\tfor scanner.Scan() {\n\t\tline := scanner.Text() // Get the current line.\n\n\t\t// If there is a current ANSI code, append it to the builder.\n\t\tif currentAnsiCode != \"\" {\n\t\t\twrappedBuilder.WriteString(currentAnsiCode)\n\t\t}\n\n\t\t// Find all ANSI escape sequences in the current line.\n\t\tstartAnsiCodes := ansiRegex.FindAllString(line, -1)\n\t\tif len(startAnsiCodes) \u003e 0 {\n\t\t\t// Update the last ANSI escape sequence to the last one found in the line.\n\t\t\tlastAnsiCode = startAnsiCodes[len(startAnsiCodes)-1]\n\t\t}\n\n\t\t// Append the current line to the builder.\n\t\twrappedBuilder.WriteString(line)\n\n\t\t// Check if the current ANSI code needs to be reset or updated.\n\t\tif (currentAnsiCode != \"\" \u0026\u0026 !strings.HasSuffix(line, ansiResetCode)) || len(startAnsiCodes) \u003e 0 {\n\t\t\t// If the current line does not end with a reset code or if there are ANSI codes, append a reset code.\n\t\t\twrappedBuilder.WriteString(ansiResetCode)\n\t\t\t// Update the current ANSI code to the last one found in the line.\n\t\t\tcurrentAnsiCode = lastAnsiCode\n\t\t} else {\n\t\t\t// If no ANSI codes need to be maintained, reset the current ANSI code.\n\t\t\tcurrentAnsiCode = \"\"\n\t\t}\n\n\t\t// Append a newline character to the builder.\n\t\twrappedBuilder.WriteString(\"\\n\")\n\t}\n\n\t// Return the processed string with properly wrapped ANSI escape sequences.\n\treturn wrappedBuilder.String()\n}\n\nfunc expectActualTable(exp string, act string, field string, centerize bool) string {\n\tbuf := \u0026bytes.Buffer{}\n\ttable := tablewriter.NewWriter(buf)\n\n\tif centerize {\n\t\ttable.SetAlignment(tablewriter.ALIGN_CENTER)\n\t} else {\n\t\ttable.SetAlignment(tablewriter.ALIGN_LEFT)\n\t}\n\t// jsonDiff.JsonDiff()\n\texp = wrapTextWithAnsi(exp)\n\tact = wrapTextWithAnsi(act)\n\ttable.SetHeader([]string{fmt.Sprintf(\"Expect %v\", field), fmt.Sprintf(\"Actual %v\", field)})\n\ttable.SetAutoWrapText(false)\n\ttable.SetBorder(false)\n\ttable.SetColMinWidth(0, maxLineLength)\n\ttable.SetColMinWidth(1, maxLineLength)\n\ttable.Append([]string{exp, act})\n\ttable.Render()\n\treturn buf.String()\n}\n\nconst maxLineLength = 50\n\nvar ansiRegex = regexp.MustCompile(`\\x1b\\[[0-9;]*[a-zA-Z]`)\n\nvar ansiResetCode = \"\\x1b[0m\"\n\n```\n\n## 👨🏻‍💻 Let's Build Together! 👩🏻‍💻\nWhether you're a newbie coder or a wizard 🧙‍♀️, your perspective is golden. Take a peek at our:\n\n📜 [Contribution Guidelines](https://github.com/keploy/JsonDiff/blob/main/CONTRIBUTING.md)\n\n❤️ [Code of Conduct](https://github.com/keploy/keploy/blob/main/CODE_OF_CONDUCT.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeploy%2Fjsondiff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkeploy%2Fjsondiff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeploy%2Fjsondiff/lists"}