如何比较两个JSON请求?

zaq34kh6  于 2023-02-26  发布在  其他
关注(0)|答案(4)|浏览(153)

小故事:如何比较两个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).我猜encoding/json不喜欢空接口,所以问题是如何比较两个JSON块?字符串比较容易出错,所以我尽量避免。

bxgwgixi

bxgwgixi1#

在这里参加派对太晚了。
golang中有一个流行的测试包,叫做require github.com/stretchr/testify/require,它可以帮你完成这项工作。

func TestJsonEquality(t *testing.t) { 
  expected := `{"a": 1, "b": 2} `
  actual := ` {"b":   2, "a":   1}`
  require.JSONEq(t, expected, actual)
}

官方文档:https://godoc.org/github.com/stretchr/testify/require#JSONEqf

gblwokeq

gblwokeq2#

您需要传递指向DecodeUnmarshal的指针。我用func JSONEqual(a, b io.Reader)JSONBytesEqual(a, b []byte)创建了一个runnable sample,它们都返回(bool, error)。您可以通过使用bytes.NewBufferstrings.NewReader Package 预期内容来比较请求正文和静态预期内容(就像您在问题中尝试做的那样)。以下是代码:

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
bbmckpt7

bbmckpt73#

我写了一个工具来比较基于http json的响应,我忽略了顺序,你可以看看实现比较的包,并获取Equal函数:www.example.comhttps://github.com/emacampolo/gomparator/blob/master/json_util.go#L10
例如:

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))
5rgfhyps

5rgfhyps4#

考虑使用https://pkg.go.dev/github.com/wI2L/jsondiff的包来帮助计算两个JSON文档之间的差异,作为一系列RFC6902(JSON Patch)操作。

import "github.com/wI2L/jsondiff"

patch, err := jsondiff.Compare(pod, newPod)
if err != nil {
    // handle error
}
b, err := json.MarshalIndent(patch, "", "    ")
if err != nil {
    // handle error
}
os.Stdout.Write(b)

相关问题