ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

jq实现json文本对比

2022-03-26 18:04:58  阅读:204  来源: 互联网

标签:icdiff name no jq item json 文本 id


原创:打码日记(微信公众号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命令
常用网络命令总结

标签:icdiff,name,no,jq,item,json,文本,id
来源: https://www.cnblogs.com/codelogs/p/16060148.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有