Golang中如何忽略数组顺序对比两个JSON字符串是否相等
Go语言对比含乱序数组的JSON等价的实现方法
你遇到的场景核心差异是prices数组内元素顺序不同,但JSON语义中如果数组是集合类型,顺序不影响等价性,普通的字符串对比或者默认的结构体相等判断都会误判,可采用以下两种方案实现:
方案一:标准库实现(无第三方依赖)
先把JSON反序列化为结构体,对乱序数组按唯一标识排序后再用反射对比:
- 定义对应结构体
type PriceItem struct { Country string `json:"country"` Price struct { Recommended int `json:"recommended"` } `json:"price"` } type Root struct { Timestamp string `json:"timestamp"` Prices []PriceItem `json:"prices"` }
- 实现排序逻辑,按
country字段对Prices数组排序
type SortedPrices []PriceItem func (s SortedPrices) Len() int { return len(s) } func (s SortedPrices) Less(i, j int) bool { return s[i].Country < s[j].Country } func (s SortedPrices) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
- 反序列化+排序+对比
import "encoding/json" import "reflect" import "sort" func CompareJSON(a, b string) (bool, error) { var r1, r2 Root if err := json.Unmarshal([]byte(a), &r1); err != nil { return false, err } if err := json.Unmarshal([]byte(b), &r2); err != nil { return false, err } // 对两个数组都排序 sort.Sort(SortedPrices(r1.Prices)) sort.Sort(SortedPrices(r2.Prices)) // 深度对比两个结构体 return reflect.DeepEqual(r1, r2), nil }
方案二:第三方工具简化实现
如果不想手写排序逻辑,可以用go-test/deep库,开启切片按集合对比的配置即可自动忽略顺序:
import "github.com/go-test/deep" import "encoding/json" func CompareJSON(a, b string) (bool, error) { var r1, r2 Root if err := json.Unmarshal([]byte(a), &r1); err != nil { return false, err } if err := json.Unmarshal([]byte(b), &r2); err != nil { return false, err } // 配置切片视为集合对比,忽略顺序 deep.CompareSlicesAsSets = true // diffs为空说明两个结构完全等价 return len(deep.Equal(r1, r2)) == 0, nil }
注意事项
- 不要直接对比JSON原始字符串:JSON对象的字段顺序本身是无序的,字符串对比会把字段顺序不同的等价JSON误判为不等。
- 如果JSON结构不固定,可以反序列化为
map[string]interface{}类型后再用上述对比逻辑处理。
内容的提问来源于stack exchange,提问作者Mehmet Ali Büber
相关产品推荐
相关产品推荐

