[转帖] jq实现json文本对比
原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。
简介#
近期,为了给一个核心系统减负,组内决定将一些调用量大的查询接口迁移到另一个系统,由于接口逻辑比较复杂,为了保证接口逻辑一致,我们决定将一周内的请求参数在两个接口重放,并用脚本校验两边接口的响应结果。
接口返回数据是json结构的,本想用icdiff、jq来实现,但时间紧迫一时没想出来,同事用python脚本实现了这个对比,但后来又仔细想了想,找出了使用icdiff、jq实现的方法。
icdiff对比文本#
对于普通的文本对比,使用diff命令即可完成,但icdiff比diff更好用,对比结果也会更加直观。
$ text1='{"name":"apple","item_no":2}'
$ text2='{"name":"a apple","item_no":2}'
$ icdiff <(echo "$text1") <(echo "$text2")

但如果用jq格式化一下再对比,看起来会更加清晰一些。
$ icdiff <(echo "$text1"|jq .) <(echo "$text2"|jq .)

但是有时json数据可能会出现数据一样,但key的顺序不一致的问题,比如:
$ text1='{"name":"apple","item_no":2}'
$ text2='{"item_no":2,"name":"apple"}'
$ icdiff <(echo "$text1"|jq .) <(echo "$text2"|jq .)

像对象转json这种操作,是有可能出现不同机器上返回json的key顺序不同的。
好在jq提供了-S选项,可对输出json的key排序,如下:
$ icdiff <(echo "$text1"|jq -S .) <(echo "$text2"|jq -S .)

本以为这样就解决了所有问题,但在脚本运行过程中,我们又发现了新情况,json中的数组项,顺序可能不一致,如下:
$ text1='{
"order_id": 121345435624,
"waybills": [
{
"waybill_id": 1,
"name": "package1",
"items": [
{
"name": "orange",
"item_no": 1
},
{
"name": "apple",
"item_no": 2
}
]
},
{
"waybill_id": 2,
"name": "package2",
"items": [
{
"name": "pear",
"item_no": 3
},
{
"name": "banana",
"item_no": 4
}
]
}
]
}'
$ text2='{
"order_id": 121345435624,
"waybills": [
{
"waybill_id": 2,
"name": "package2",
"items": [
{
"name": "banana",
"item_no": 4
},
{
"name": "pear",
"item_no": 3
}
]
},
{
"waybill_id": 1,
"name": "package1",
"items": [
{
"name": "orange",
"item_no": 1
},
{
"name": "apple",
"item_no": 2
}
]
}
]
}'
$ icdiff <(echo "$text1"|jq -S .) <(echo "$text2"|jq -S .)

因为icdiff没法识别这种顺序区别,它只是逐行进行对比的,虽然两个json逻辑上是一样的,但它区别不出来。
程序中以下情况会造成这种顺序区别:
- 从数据库中查询数据时,如果SQL没有order by语句,那么返回结果的顺序是不确定的。
- 如果数据是在Map中,当用values()变换成List返回数据时,返回结构的顺序也是不确定的。
要解决这种情况还真挺麻烦的,因为需要对json中的数组进行排序,然后再进行对比,之前就是这里想不出来怎么实现。
但在后来,我又仔细的看了看jq的man文档,发现了一个有用的函数walk,然后就试了试,还真发现可以实现。
$ json_sort='walk(if type == "array" and length >0 then (if .[0].item_no then sort_by(.item_no) elif .[0].waybill_id then sort_by(.waybill_id) else. end) else . end)'
$ icdiff <(echo "$text1"|jq -S "$json_sort") <(echo "$text2"|jq -S "$json_sort")

总结#
Linux命令结合起来,总能产生更大的作用,当然这也需要付出一些折腾时间啊。
往期内容#
作者:打码日记
出处:https://www.cnblogs.com/codelogs/p/16060148.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
[转帖] jq实现json文本对比的更多相关文章
- XML与JSON的对比
XML与JSON的对比 1.各自定义 XML 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类 ...
- JSON C# Class Generator是一个从JSON文本中生成C#内的应用程序
JSON C# Class Generator是一个从JSON文本中生成C#内的应用程序 .NET平台开源项目速览(18)C#平台JSON实体类生成器JSON C# Class Generator ...
- jq处理JSON数据, jq Manual (development version)
jq 允许你直接在命令行下对 JSON 进行操作,包括分片.过滤.转换等等.让我们通过几个例子来说明 jq 的功能:一.输出格式化,漂亮的打印效果如果我们用文本编辑器打开 JSON,有时候可能看起来会 ...
- 使用 Json.Net 对Json文本进行 增删改查
JSON 已经成为当前主流交互格式, 如何在C#中使用 Json.Net 对Json文本进行 增删改查呢?见如下代码 #region Create (从零创建) public static strin ...
- php 两段文本对比,不同的文字显示高亮
php 两段文本对比,不同的文字显示高亮[下面这个只能区分错误后面的..] <?php $str1 ="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwgg ...
- JSON文本转换为JSONArray 转换为 List<Object>
package com.beijxing.TestMain; import java.io.File; import java.io.IOException; import java.util.Arr ...
- json文本装换为JSONArray
package com.beijxing.TestMain; import java.io.File; import java.io.IOException; import org.apache.co ...
- 一个Json结构对比的Python小工具兼谈编程求解问题
先上代码. jsondiff.py #!/usr/bin/python #_*_encoding:utf-8_*_ import argparse import json import sys rel ...
- 21SpringMvc_异步发送表单数据到Bean,并响应JSON文本返回(这篇可能是最重要的一篇了)
这篇文章实现三个功能:1.在jsp页面点击一个按钮,然后跳转到Action,在Action中把Emp(int id ,String salary,Data data)这个实体变成JSON格式返回到页面 ...
- 高性能JSON工具-FastJson处理超大JSON文本
使用阿里开源类库FastJson,当需要处理超大JSON文本时,需要Stream API,在fastjson-1.1.32版本中开始提供Stream API.文档参考GitHub:https://gi ...
随机推荐
- GaussDB技术解读系列丨运维自动驾驶探索
本文分享自华为云社区<DTCC 2023专家解读 | GaussDB技术解读系列之运维自动驾驶探索>,作者:GaussDB 数据库 . 近日,在第14届中国数据库技术大会(DTCC2023 ...
- 火山引擎 DataLeap:数据秒级生产,揭秘电商实时数仓最佳实践!
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 一年一度的「三八大促」刚刚落下帷幕,各大电商平台纷纷推出补贴.营销等玩法,力图推动持续增长.而电商平台持续增长,离 ...
- 在WPF应用中使用FastReport.WPF报表模块
FastReport是一个非常不错的报表组件,在Winform应用中常常使用它进行报表的设计.预览展现.打印或者导出文件(PDF.Excel)等,可以设计打印各种各样的报表,本篇随笔继续介绍当前最新的 ...
- BAPI_PO_CHANGE 采购订单修改服务
修改服务页签里面的价格和数量,达到修改净价和条件里面金额的目的 数据可以通过采购订单查询ESLH和ESLL表获取 "------------------------------------- ...
- 《Flask Web 开发指南 pt.1》
最近在看辉哥的<Flask Web 开发实战>,这才有了<Flask Web 开发指南>系列的文章,偏向学习笔记多一点,也有实战的内容 看下这个系列的文章我能写多少篇 :) 愚 ...
- SQL常用日期格式化转换与百分数转换
目录 SQL将小数转为保留两位的百分数 常用的日期格式化 补充: 秒/毫秒转为持续时间 常用拼接方式: 本篇开启数据库在工作中常用到的格式转换与工具,欢迎大家评论留言 SQL将小数转为保留两位的百分数 ...
- SAE 2.0,让容器化应用开发更简单
云原生容器化应用托管模式的演变 云原生这个概念从提出,到壮大,再到今天的极大普及,始终处于一个不断演进和革新的过程中.云原生体系下应用的托管形态是随着企业应用架构在不断演进的.最早的应用大多是集中式. ...
- <vue 路由 4、嵌套路由>
一.效果 点击about后,新闻和体育属于about的子路由调用的页面 知识点说明 路由里使用children属性可以实现路由的嵌套 三.代码结构 注:主要是标红的几个文件 四.代码 重新编写这几个文 ...
- CPLEX通过Python API获取Gap值的方法
写在前面 最近在使用Cplex求解模型,尽管Cplex的Python API会自动输出引擎日志,但在多次求解中一次次看引擎日志找Gap值并做实验记录很麻烦,所以需要找到获取Gap值的方法.然而我在Cp ...
- 用线性二次模型建模大型数据中心,基于 MPC 进行冷却控制
目录 一个总述 reviews 0 abstract 1 intro 2 related work 3 DC cooling(问题定义) 4 MPC(method) 4.1 Model structu ...