Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare two JSON requests?

Tags:

json

go

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.

like image 751
Anthony Hunt Avatar asked Sep 05 '15 02:09

Anthony Hunt


People also ask

How do you compare two JSON responses?

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.

How can we compare two JSON files?

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.

How to compare two JSON responses during API testing?

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.

How can I compare two endpoints in a JSON file?

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.

How do I compare two JSON objects in Java?

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 } }

How do I compare two jsonnode variables?

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 } }


2 Answers

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

like image 84
Highstead Avatar answered Oct 18 '22 13:10

Highstead


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
like image 20
twotwotwo Avatar answered Oct 18 '22 13:10

twotwotwo