一尘不染

如何比较两个JSON请求?

go

短篇小说:如何比较两个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块?字符串比较容易出错,因此我尝试避免这种情况。


阅读 265

收藏
2020-07-02

共1个答案

一尘不染

您需要将指针传递给DecodeUnmarshal。我用和放了一个可运行的示例,都返回。您可以使用或封装您的期望内容,从而将请求正文与您的静态期望内容进行比较(就像您要在问题中尝试做的那样)。这是代码: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
2020-07-02