当前位置: > > > > 如何比较不同顺序的 JSON?
如何比较不同顺序的 JSON?
来源:stackoverflow
2024-04-25 08:00:35
0浏览
收藏
在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天米云就整理分享《如何比较不同顺序的 JSON?》,聊聊,希望可以帮助到正在努力赚钱的你。
问题内容
我正在尝试使用黄金文件实现测试,但是,我的函数生成的 json 顺序有所不同,但保持相同的值。我已经实现了这里使用的比较方法:
如何比较两个 json 请求?
但它依赖于顺序。正如布拉德在此所述:
json 对象是无序的,就像 go 映射一样。如果 您取决于特定实现序列化 json 的顺序 对象,你有一个错误。
我编写了一些示例代码来模拟我的困境:
package main
import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"os"
"reflect"
"time"
)
type example struct {
Name string
Earnings float64
}
func main() {
slice := GetSlice()
gfile, err := ioutil.ReadFile("testdata/example.golden")
if err != nil {
fmt.Println(err)
fmt.Println("Failed reading golden file")
}
testJSON, err := json.Marshal(slice)
if err != nil {
fmt.Println(err)
fmt.Println("Error marshalling slice")
}
equal, err := JSONBytesEqual(gfile, testJSON)
if err != nil {
fmt.Println(err)
fmt.Println("Error comparing JSON")
}
if !equal {
fmt.Println("Restults don't match JSON")
} else {
fmt.Println("Success!")
}
}
func GetSlice() []example {
t := []example{
example{"Penny", 50.0},
example{"Sheldon", 70.0},
example{"Raj", 20.0},
example{"Bernadette", 200.0},
example{"Amy", 250.0},
example{"Howard", 1.0}}
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(t), func(i, j int) { t[i], t[j] = t[j], t[i] })
return t
}
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 WriteTestSliceToFile(arr []example, filename string) {
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("failed creating file: %s", err)
}
datawriter := bufio.NewWriter(file)
marshalledStruct, err := json.Marshal(arr)
if err != nil {
fmt.Println("Error marshalling json")
fmt.Println(err)
}
_, err = datawriter.Write(marshalledStruct)
if err != nil {
fmt.Println("Error writing to file")
fmt.Println(err)
}
datawriter.Flush()
file.Close()
}
解决方案
已订购 json 。将切片编码为 json 数组时,json.marshal 函数会保留顺序。
json 未排序。 json.marshal 函数按排序键顺序写入对象成员,如 中所述。
bradfitz 评论 json 对象排序与此问题无关:
- 问题中的应用程序使用的是 json 数组,而不是 json 对象。
- 在 brad 发表评论几年后,该软件包已更新为按排序键顺序写入对象字段。
要在忽略顺序的情况下比较切片,请在比较之前对两个切片进行排序。这可以在编码为 json 之前或从 json 解码之后完成。
sort.Slice(slice, func(i, j int) bool {
if slice[i].Name != slice[j].Name {
return slice[i].Name < slice[j].Name
}
return slice[i].Earnings < slice[j].Earnings
})
对于单元测试,您可以使用 testify 中的 assert.jsoneq。如果您需要以编程方式执行此操作,可以遵循 jsoneq 函数的代码。
文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《如何比较不同顺序的 JSON?》文章吧,也可关注米云公众号了解相关技术文章。
