Short Story: How can I compare two chunks of JSON? The code below errors out.
var j, j2 interface{}
b := []byte(srv.req)
if err := json.Unmarshal(b, j); err !=nil{
t.Errorf("err %v, req %s", err, b)
return
}
d := json.NewDecoder(r.Body)
if err := d.Decode(j2); err !=nil{
t.Error(err)
return
}
if !reflect.DeepEqual(j2, j){
t.Errorf("j %v, j2 %v", j, j2)
return
}
Long Story:
I'm doing some E2E testings and part of this I need to compare the requested JSON body with the received JSON. To do this I've tried to unmarshal the expected and received json to an empty interface (to avoid any type mistakes) but I get an error:
json: Unmarshal(nil)
. I guess encoding/json doesn't like the empty interface so the question is how can I compare two chunks of JSON? A string comparison would be error prone so I'm trying to avoid that.
Comparing Json: Comparing json is quite simple, we can use '==' operator, Note: '==' and 'is' operator are not same, '==' operator is use to check equality of values , whereas 'is' operator is used to check reference equality, hence one should use '==' operator, 'is' operator will not give expected result.
You can also directly compare two JSON files by specifying their urls in the GET parameters url1 and url2. Then you can visualize the differences between the two JSON documents.
We may need to compare two JSON during API testing. For example – If we are going to get the same JSON response for an API every time or some parts of the response are always constant then instead of writing some logic to assert them, we can directly compare with an existing JSON response. We have a couple of good Java libraries to do.
The most basic solution would be to use an online JSON comparer (like this one or this one ). This would imply though that you have to manually input the responses of the endpoints under test in the online comparer and repeat for every endpoint. Not too elegant, if you ask me.
Compare Two Simple JSON Objects Let’s begin by using the JsonNode.equals method. The equals () method performs a full (deep) comparison. Suppose we have a JSON string defined as the s1 variable: { "employee" : { "id": "1212" , "fullName": "John Miles" , "age": 34 } }
Let’s begin by using the JsonNode.equals method. The equals () method performs a full (deep) comparison. Suppose we have a JSON string defined as the s1 variable: { "employee" : { "id": "1212" , "fullName": "John Miles" , "age": 34 } }
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With