简短故事:我如何比较两个JSON块?以下代码出错。
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
}
长篇故事:
我正在进行一些E2E测试,其中一部分需要将所请求的JSON主体与收到的JSON进行比较。为此,我尝试将预期和接收的json解组为空接口(以避免任何类型错误)但我收到错误:
json: Unmarshal(nil)
。我猜编码/ json不喜欢空接口所以问题是如何比较两个JSON块?字符串比较容易出错,所以我试图避免这种情况。
答案 0 :(得分:3)
您需要将指针传递给Decode
和Unmarshal
。我提出runnable sample func JSONEqual(a, b io.Reader)
和JSONBytesEqual(a, b []byte)
,都返回(bool, error)
。您可以使用bytes.NewBuffer
或strings.NewReader
将预期内容包装起来,将请求正文与您的静态预期内容进行比较(就像您在问题中尝试做的那样)。这是代码:
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)
}
输出:
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
答案 1 :(得分:3)
在这里参加晚会超级晚。
golang中有一个流行的测试包,称为require 0x80000000
,它将为您完成这项工作。
github.com/stretchr/testify/require
GoDocs:https://godoc.org/github.com/stretchr/testify/require#JSONEqf
答案 2 :(得分:1)
我编写了一个用于比较基于http json的响应的工具,但忽略了顺序。您可以看一下实现比较的包并获取Equal函数: https://github.com/ecampolo/gomparator/blob/master/internal/platform/json/json.go
例如:
b1 := []byte(`{"x": {"t": 1, "s": 2}, "z": 1}`)
b2 := []byte(`{"z": 1, "x": {"s": 2, "t": 1}}`)
j1, _ := Unmarshal(b1)
j2, _ := Unmarshal(b2)
assert.True(t, Equal(j1, j2))