Super late to the party here.
There is a popular testing package in golang called require github.com/stretchr/testify/require and it will do this for you.
func TestJsonEquality(t *testing.t) {
expected := `{"a": 1, "b": 2} `
actual := ` {"b": 2, "a": 1}`
require.JSONEq(t, expected, actual)
}
GoDocs: https://godoc.org/github.com/stretchr/testify/require#JSONEqf
Answer from Highstead on Stack OverflowSuper late to the party here.
There is a popular testing package in golang called require github.com/stretchr/testify/require and it will do this for you.
func TestJsonEquality(t *testing.t) {
expected := `{"a": 1, "b": 2} `
actual := ` {"b": 2, "a": 1}`
require.JSONEq(t, expected, actual)
}
GoDocs: https://godoc.org/github.com/stretchr/testify/require#JSONEqf
You need to pass pointers to Decode and Unmarshal. I put up a runnable sample with func JSONEqual(a, b io.Reader) and JSONBytesEqual(a, b []byte), both returning (bool, error). You can compare a request body to your static expected content (like you're trying to do in the question) by wrapping your expected content using bytes.NewBuffer or strings.NewReader. Here's the code:
package main
import (
"encoding/json"
"fmt"
"io"
"reflect"
)
// JSONEqual compares the JSON from two Readers.
func JSONEqual(a, b io.Reader) (bool, error) {
var j, j2 interface{}
d := json.NewDecoder(a)
if err := d.Decode(&j); err != nil {
return false, err
}
d = json.NewDecoder(b)
if err := d.Decode(&j2); err != nil {
return false, err
}
return reflect.DeepEqual(j2, j), nil
}
// JSONBytesEqual compares the JSON in two byte slices.
func JSONBytesEqual(a, b []byte) (bool, error) {
var j, j2 interface{}
if err := json.Unmarshal(a, &j); err != nil {
return false, err
}
if err := json.Unmarshal(b, &j2); err != nil {
return false, err
}
return reflect.DeepEqual(j2, j), nil
}
func main() {
a := []byte(`{"x": ["y",42]}`)
b := []byte(`{"x": ["y", 42]}`)
c := []byte(`{"z": ["y", "42"]}`)
empty := []byte{}
bad := []byte(`{this? this is a test.}`)
eq, err := JSONBytesEqual(a, b)
fmt.Println("a=b\t", eq, "with error", err)
eq, err = JSONBytesEqual(a, c)
fmt.Println("a=c\t", eq, "with error", err)
eq, err = JSONBytesEqual(a, empty)
fmt.Println("a=empty\t", eq, "with error", err)
eq, err = JSONBytesEqual(a, bad)
fmt.Println("a=bad\t", eq, "with error", err)
}
It outputs:
a=b true with error <nil>
a=c false with error <nil>
a=empty false with error EOF
a=bad false with error invalid character 't' looking for beginning of object key string
Well, it came to me when I was writing 101st test for API. There are many asserters in golang world, but I needed readable output. Especially when it came to output a diff for 2 huge objects - expected and actual API responses. I got inspired by http://tlrobinson.net/projects/javascript-fun/jsondiff/ and implemented this one for Go: https://github.com/elgris/jsondiff
Hope you will find it useful for your tests. Or point me to another useful tool that visualizes diffs in golang world :)
Hey everyone, I am calling an api which returns a json. And i have. json file on local. I want to check if they are same or not. Do I have to loop through both jsons and compare the values or is there any better way of solving this problem.
Hey r/golang community,
I've been grappling with a recurring challenge in my work: comparing large, deeply nested JSON files. To tackle this, I created a CLI tool in Go that helps highlight differences between two JSON files with high precision.
The tool is relatively compact, about 200 lines of code, and handles different types of changes well, including additions, deletions, and type mismatches. However, I'm looking to improve how differences within arrays are displayed. Currently, if an item at the beginning of an array is modified or removed, all subsequent items are marked as changed, which isn't very helpful for quick analysis.
Here's where I could use your collective wisdom:
Visualization Techniques: Does anyone have suggestions for more intuitive ways to display array differences? Maybe a method that effectively pinpoints and isolates changes without cascading the entire array?
Code Feedback: I'd love to get some feedback on the implementation. I'm sure there are optimizations and best practices that I could apply to enhance the tool's performance and usability.
I'm looking forward to your insights and suggestions. Let's make JSON comparisons easier for everyone!
You can check out the tool and contribute here: https://github.com/phplego/jcmp
Thank you all in advance!
There is no easy way you can do this. You have to write a recursive comparison function, something like this:
func compareKeys(in1,in2 interface{}) bool {
if m1, ok:=in1.(map[string]interface{}); ok {
if m2, ok:=in2.(map[string]interface{}); ok {
return compareMaps(m1,m2)
}
return false
}
if a1,ok := in1.([]interface{}); ok {
if a2, ok:=in2.([]interface{}); ok {
return compareArrays(a1, a2);
}
return false
}
if _, ok:=in2.(map[string]interface{}); ok {
return false
}
if _, ok:=in2.([]interface{}); ok {
return false
}
return true
}
func compareMaps(in1, in2 map[string]interface{}) bool {
if len(in1)!=len(in2) {
return false
}
for k,v:=range in1 {
if v2, ok:=in2[k]; ok {
if !compareKeys(v, v2) {
return false
}
} else {
return false
}
}
return true
}
func compareArrays(in1, in2 []interface{}) bool {
if len(in1)!=len(in2) {
return false
}
for i:=range in1 {
if !compareKeys(in1[i],in2[i]) {
return false
}
}
return true
}
You may compare jour strings like this:https://pkg.go.dev/github.com/stretchr/testify/require#JSONEqf
if assert.JSONEqf(t, {"hello": "world", "foo": "bar"}, {"foo": "bar", "hello": "world"}, "error message %s", "formatted") {
println("#############################################")
}