我比较了两个相同的 json 文档。一份来自 Gin,一份来自 MongoDB。 数据类型为:
map[string]interface{}
比较返回 false。
res := reflect.DeepEqual(Data, result)
我使用以下代码来查看差异:
fmt.Printf("expectedjson: %#v\n", result)
fmt.Printf("unmarshalled: %#v\n", data)
结果:
expectedjson: map[string]interface {}{"Connections":primitive.A{}, "Devices":primitive.A{map[string]interface {}{"GUID":"1234", "bmk":"RevPi Core V1.2", "comment":"This is a RevPiCore Device", "extend":map[string]interface {}{}, "id":"1234", "inp":map[string]interface {}{"0":primitive.A{"RevPiStatus", "0", "8", "0", true, "0000", "", ""}}
unmarshalled: map[string]interface {}{"Connections":[]interface {}{}, "Devices":[]interface {}{map[string]interface {}{"GUID":"1234", "bmk":"RevPi Core V1.2", "comment":"This is a RevPiCore Device", "extend":map[string]interface {}{}, "id":"1234", "inp":map[string]interface {}{"0":[]interface {}{"RevPiStatus", "0", "8", "0", true, "0000", "", ""}}
正如你所看到的,通过从 MongoDB 收集数据并对其进行解码,
[]interface {}
是 primitive.A
类型。
我使用以下代码来解码来自 MongoDB 的数据:
err = collection.FindOne(context.TODO(), filter, opts).Decode(&result)
比较这些的最佳方法是什么?才能得到真正的回报。
我尝试递归遍历整个文档并找到
primitive.A
类型,但我找不到将它们更改为 []interface {}
的方法。
我使用了这个代码:
walk(reflect.ValueOf(&result))
func walk(v reflect.Value) {
fmt.Printf("Visiting %v\n", v)
/*
code to change primitive.A to interface
*/
if v.Elem().Type().String() == "primitive.A" {
fmt.Println("---", v.Elem(), " : ", v.Elem().Type())
v.Interface()
fmt.Println(v.Elem().Type())
}
// Indirect through pointers and interfaces
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
v = v.Elem()
}
switch v.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < v.Len(); i++ {
walk(v.Index(i))
}
case reflect.Map:
for _, k := range v.MapKeys() {
walk(v.MapIndex(k))
}
default:
// handle other types
}
}
您似乎正在尝试比较存储在不同数据结构中的 JSON 文档:一份来自 Gin,一份来自 MongoDB,两者都使用数据类型 map[string]interface{}。您正在使用 Reflect.DeepEqual 来比较它们,但它没有给出预期的结果。
从您的描述来看,主要问题似乎是两个文档中的数组(切片)类型不同(primitive.A 与 []interface{})。 Primitive.A 是 MongoDB 的 Go 驱动程序使用的自定义类型,它与标准的 []interface{} 类型不直接匹配。
为了有效地比较这两种结构,您需要进行考虑到这些类型差异的自定义比较。您的递归方法是朝着正确方向迈出的一步,但它需要一些修改来处理 Primitive.A 到 []interface{} 的转换。
以下是如何修改代码来实现此目的:
func walk(v reflect.Value) {
if v.Type().String() == "primitive.A" {
// Convert primitive.A to []interface{}
var result []interface{}
for i := 0; i < v.Len(); i++ {
result = append(result, v.Index(i).Interface())
}
v.Set(reflect.ValueOf(result))
}
// Indirect through pointers and interfaces
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
v = v.Elem()
}
switch v.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < v.Len(); i++ {
walk(v.Index(i))
}
case reflect.Map:
for _, k := range v.MapKeys() {
walk(v.MapIndex(k))
}
default:
// handle other types
}
}
在此代码中,当您遇到primitive.A类型的值时,它将其转换为interface{}的切片并更新反射中的值以匹配所需的结构。此修改应确保两个文档之间的比较按预期进行。
请记住,此方法适用于处理类型差异,但您仍应仔细考虑如何比较文档中的实际值。根据您的用例,您可能还需要处理其他类型和特定字段比较。