Breve História: Como posso comparar dois trechos de JSON? O código abaixo está errado.
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
}
Longa história: Eu estou fazendo alguns testes E2E e parte disso eu preciso comparar o corpo JSON solicitado com o JSON recebido. Para fazer isso eu tentei unmarshal o json esperado e recebido para uma interface vazia (para evitar erros de qualquer tipo), mas Eu recebo um erro:
json: Unmarshal(nil)
. Eu acho que codificação / json não gosta da interface vazia, então a questão é como posso comparar dois pedaços de JSON? Uma comparação de seqüência de caracteres seria propenso a erros, então eu estou tentando evitar isso.
Respostas:
2 para resposta № 1Você precisa passar ponteiros para Decode
e Unmarshal
. Eu coloquei um amostra executável com func JSONEqual(a, b io.Reader)
e JSONBytesEqual(a, b []byte)
ambos retornando (bool, error)
. Você pode comparar um corpo de solicitação ao seu conteúdo esperado estático (como você está tentando fazer na pergunta) envolvendo o conteúdo esperado usando bytes.NewBuffer
ou strings.NewReader
. Aqui está o código:
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=bt", eq, "with error", err)
eq, err = JSONBytesEqual(a, c)
fmt.Println("a=ct", eq, "with error", err)
eq, err = JSONBytesEqual(a, empty)
fmt.Println("a=emptyt", eq, "with error", err)
eq, err = JSONBytesEqual(a, bad)
fmt.Println("a=badt", eq, "with error", err)
}
Ele produz:
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