json - 如何比较不同顺序的JSON?

标签 json go

我正在尝试用黄金文件实现测试,但是,我的函数生成的JSON顺序不同,但保持相同的值。我已经实现了这里使用的比较方法:

How to compare two JSON requests?

但这是顺序依赖的。并如brad的here所述:

JSON objects are unordered, just like Go maps. If you're depending on the order that a specific implementation serializes your JSON objects in, you have a bug.



我编写了一些示例代码来模拟我的困境:
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 arrays已订购。将 slice 编码为JSON数组时,json.Marshal函数将保留顺序。

JSON objects不排序。 json.Marshal函数按照the documentation中所述的排序键顺序写入对象成员。

bradfitz注释JSON对象的排序与此问题无关:

  • 问题中的应用程序正在使用JSON数组,而不是JSON对象。
  • 该软件包已更新,可以在布拉德发表评论后的第二年按排序的键顺序写入对象字段。

  • 要在忽略顺序的情况下比较 slice ,请在比较之前对两个 slice 进行排序。这可以在编码为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
    })
    

    关于json - 如何比较不同顺序的JSON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58984126/

    相关文章:

    c# - Json.NET 中的 JConstructor 和 JRaw

    json - 如何编写 jolt 规范以将不同对象转换为数组

    json - Flutter发送post请求返回http错误500

    json - 使用 ColdFusion cfhttp 连接到远程 API

    go - 我正在尝试通过2部分API调用服务以进行openshift。 GET的结果用作POST的有效负载

    go - 错误 : failed to initialize database, 拨号 tcp 时遇到错误:0:connectex:请求的地址在其上下文中无效

    go - Go中返回无效结构的惯用方式

    go - 为什么 go-get 尝试从远程位置下载本地代码?

    datetime - 将格式化时间转换为 UTC 毫秒

    java - 使用java提取JSON字段