[转帖] jq实现json文本对比

jq,实现,json,文本,对比 · 浏览次数 : 0

小编点评

## 针对json数据对比的方法总结 **1. 使用icdiff:** * idiff 比 diff 更易于理解和使用,因为它提供了更直观的输出格式。 * 使用 -S 选项可以对输出 json 的 key 排序。 **2. 使用jq:** * jq 可以使用 -S 选项对输出 json 的 key 排序。 * 使用 walk 函数可以递归地处理 json 数据,并实现排序。 **3. 结合使用 idiff 和 jq:** * 使用 jq 的 walk 函数对 json 数据进行排序后,可以使用 idiff 进行对比。 * 这可以帮助克服 icdiff 对顺序敏感的缺点。 **4. 解决 SQL 中 order by 语句带来的顺序问题:** * 可以使用 idiff 或 jq 的 walk 函数进行排序,并在排序前添加一个固定排序条件。 * 例如,可以先排序按照 order_id,然后按照 item_no。 **5. 示例代码:** ```python import idiff # 模拟 json 数据 text1 = '{"order_id": 121345435624, "waybills": [...]}' text2 = '{"order_id": 121345435624, "waybills": [...]}' # 使用 idiff 进行对比 result = idiff.diff(text1, text2) # 使用 jq 进行排序 sorted_text1 = jq -S '.waybills | sort_by(.item_no)"(text1) sorted_text2 = jq -S '.waybills | sort_by(.item_no)"(text2) # 打印结果 print(result) print(sorted_text1) print(sorted_text2) ``` **注意:** * 代码需要包含 idiff 和 jq 的安装路径。 * 可以根据实际情况修改代码,例如添加处理空数组或其他特殊情况的逻辑。

正文

 

 

原创:打码日记(微信公众号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")

icdiff1

但如果用jq格式化一下再对比,看起来会更加清晰一些。

$ icdiff <(echo "$text1"|jq .) <(echo "$text2"|jq .)

icdiff2

但是有时json数据可能会出现数据一样,但key的顺序不一致的问题,比如:

$ text1='{"name":"apple","item_no":2}'
$ text2='{"item_no":2,"name":"apple"}'
$ icdiff <(echo "$text1"|jq .) <(echo "$text2"|jq .)

icdiff3
像对象转json这种操作,是有可能出现不同机器上返回json的key顺序不同的。

好在jq提供了-S选项,可对输出json的key排序,如下:

$ icdiff <(echo "$text1"|jq -S .) <(echo "$text2"|jq -S .)

icdiff4

本以为这样就解决了所有问题,但在脚本运行过程中,我们又发现了新情况,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 .)  

icdiff5
因为icdiff没法识别这种顺序区别,它只是逐行进行对比的,虽然两个json逻辑上是一样的,但它区别不出来。
程序中以下情况会造成这种顺序区别:

  1. 从数据库中查询数据时,如果SQL没有order by语句,那么返回结果的顺序是不确定的。
  2. 如果数据是在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")

icdiff6

总结#

Linux命令结合起来,总能产生更大的作用,当然这也需要付出一些折腾时间啊。

往期内容#

Linux文本命令技巧(下)
Linux文本命令技巧(上)
原来awk真是神器啊
好用的parallel命令
常用网络命令总结

作者:打码日记

出处:https://www.cnblogs.com/codelogs/p/16060148.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

与[转帖] jq实现json文本对比相似的内容:

[转帖] jq实现json文本对比

原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介# 近期,为了给一个核心系统减负,组内决定将一些调用量大的查询接口迁移到另一个系统,由于接口逻辑比较复杂,为了保证接口逻辑一致,我们决定将一周内的请求参数在两个接口重放,并用脚本校验两边接口的响应结果。接口返回数据是

[转帖] jq命令用法总结

https://www.cnblogs.com/codelogs/p/16324928.html 原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介# 如果说要给Linux文本三剑客(grep、sed、awk)添加一员的话,我觉得应该是jq命令,因为jq命令是用来处

[转帖]

Linux ubuntu20.04 网络配置(图文教程) 因为我是刚装好的最小系统,所以很多东西都没有,在开始配置之前需要做下准备 环境准备 系统:ubuntu20.04网卡:双网卡 网卡一:供连接互联网使用网卡二:供连接内网使用(看情况,如果一张网卡足够,没必要做第二张网卡) 工具: net-to

[转帖]

https://cloud.tencent.com/developer/article/2168105?areaSource=104001.13&traceId=zcVNsKTUApF9rNJSkcCbB 前言 Redis作为高性能的内存数据库,在大数据量的情况下也会遇到性能瓶颈,日常开发中只有时刻

[转帖]ISV 、OSV、 SIG 概念

ISV 、OSV、 SIG 概念 2022-10-14 12:29530原创大杂烩 本文链接:https://www.cndba.cn/dave/article/108699 1. ISV: Independent Software Vendors “独立软件开发商”,特指专门从事软件的开发、生产、

[转帖]Redis 7 参数 修改 说明

2022-06-16 14:491800原创Redis 本文链接:https://www.cndba.cn/dave/article/108066 在之前的博客我们介绍了Redis 7 的安装和配置,如下: Linux 7.8 平台 Redis 7 安装并配置开机自启动 操作手册https://ww

[转帖]HTTPS中间人攻击原理

https://www.zhihu.com/people/bei-ji-85/posts 背景 前一段时间,公司北京地区上线了一个HTTPS防火墙,用来监听HTTPS流量。防火墙上线之前,邮件通知给管理层,我从我老大那里听说这个事情的时候,说这个有风险,然后意外地发现,很多人原来都不知道HTTPS防

[转帖]关于字节序(大小端)的一点想法

https://www.zhihu.com/people/bei-ji-85/posts 今天在一个技术群里有人问起来了,当时有一些讨论(不完全都是我个人的观点),整理一下: 为什么网络字节序(多数情况下)是大端? 早年设备的缓存很小,先接收高字节能快速的判断报文信息:包长度(需要准备多大缓存)、地

[转帖]awk提取某一行某一列的数据

https://www.jianshu.com/p/dbcb7fe2da56 1、提取文件中第1列数据 awk '{print $1}' filename > out.txt 2、提取前2列的文件 awk `{print $1,$2}' filename > out.txt 3、打印完第一列,然后打

[转帖]awk 中 FS的用法

https://www.cnblogs.com/rohens-hbg/p/5510890.html 在openwrt文件 ar71xx.sh中 查询设备类型时,有这么一句, machine=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /machine/ {print $2}' /