Linux Shell jq比较json是否相同

问题:shell下使用jq比较两个json是否相等,第一个难点是KEY需要排序,第二个难点是array需要排序

Jq 本身提供-S参数使key进行排序

$ jq -c . a

{"array":["fdsfd","12321","g9023ijio"],"zfdsf":"fdsfsd","vfdsadsad":123,"array2":[123,4324,421321],"9fdsfds":123}

$ jq -c -S . a

{"9fdsfds":123,"array":["fdsfd","12321","g9023ijio"],"array2":[123,4324,421321],"vfdsadsad":123,"zfdsf":"fdsfsd"}

不过无法处理array.

jq提供了walk功能可以对所有的key进行遍历,同时他的example1就展示了如何对array进行排序,但apt中提供的jq不具有这个功能。

walk(f)
The walk(f) function applies f recursively to every component of the input entity. When an array is encountered, f is first applied to its elements and then to the array itself; when an object is encountered, f is first applied to all the values and then to the object. In practice, f will usually test the type of its input, as illustrated in the following examples. The first example highlights the usefulness of processing the elements of an array of arrays before processing the array itself. The second example shows how all the keys of all the objects within the input can be considered for alteration.
Examples
jq 'walk(if type == "array" then sort else . end)'
   Input [[4, 1, 7], [8, 5, 2], [3, 6, 9]]
  Output [[1,4,7],[2,5,8],[3,6,9]]
jq 'walk( if type == "object" then with_entries( .  key |= sub( "^_+"; "") ) else . end )'
  Input [ { "_a": { "__b": 2 } } ]
  Output [{"a":{"b":2}}]

在github上找到了可以在jq1.5中使用walk的方法

# Apply f to composite entities recursively, and to atoms
def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
  elif type == "array" then map( walk(f) ) | f
  else f
  end;

最后写成了这个样子,

#!/bin/bash

# set -x
a=$1
b=$2

a_format=$(echo ${a} |jq 'def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
  elif type == "array" then map( walk(f) ) | f
  else f
  end;walk(if type == "array" then sort  else .  end)')
if [ $? -ne 0 ] ; then
    exit 1
fi
b_format=$(echo ${b} |jq 'def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
  elif type == "array" then map( walk(f) ) | f
  else f
  end;walk(if type == "array" then sort  else .  end)')
if [ $? -ne 0 ] ; then
    exit 1
fi

a_md5=$(echo ${a_format}|md5sum|cut -f1 -d" ")
b_md5=$(echo ${b_format}|md5sum|cut -f1 -d" ")

if [ "x${a_md5}" = "x${b_md5}" ] ; then
    exit 0

fi

exit 1

你可能感兴趣的:(Linux Shell jq比较json是否相同)