3
0

More than 3 years have passed since last update.

AWS CLIで出力したJSONをソートして順序のゆらぎを吸収したメモ

Last updated at Posted at 2021-02-11

AWSの環境構築内容を履歴管理したくて、AWS CLIで出力したJSONをバージョン管理ツールにコミットして差分確認することにしたのですが、AWS CLIで出力されるJSONの配列などの順序が毎回必ずしも同じではなく、変更が無いのにDiffが出ることがありました。
そこで、JSONをソート出来ればと思ったのですが、いろいろ検索してもJSONを良い感じにソートできるLinuxコマンドが見つからなく、JSONをソートするRubyをチャカっと書いて、その場しのぎをしたのでメモ。
JSONの要素のキーと値の両方を文字列として接続して、その文字列でソートして、同じ内容のJSONであれば表記の順序がまちまちでも同じ出力結果になるように出来たと思います。
もっと良い方法など気づいた事がありましたらコメント頂けると幸いです。

sort_json.rb
#!<パス>/ruby
# -*- coding: utf-8 -*-

require 'json'

def sortHash(h)
  str = ''
  new_hash = Hash.new
  h.sort.to_h.each do |k, v|
    new_v, s = sortObject(v)
    new_hash[k] = new_v
    str += k.to_s + s
  end
  return new_hash, str
end

def sortArray(a)
  tmp_hash = Hash.new
  a.each do |v|
    new_v, s = sortObject(v)
    tmp_hash[s] = new_v
  end
  str = ''
  new_array = []
  tmp_hash.sort.to_h.each do |k, v|
    str += k
    new_array << v
  end
  return new_array, str
end

def sortObject(o)
  if o.class == Hash
    return sortHash(o)
  elsif o.class == Array
    return sortArray(o)
  else
    return o, o.to_s
  end
end

begin
  hash = JSON.load(STDIN.read)
  hash, str = sortObject(hash)
  json_str = JSON.pretty_generate(hash)
  puts json_str
end

<実行例>

$ echo '{"c":1, "b":2, "a":3}' | ./sort_json.rb
{
  "a": 3,
  "b": 2,
  "c": 1
}
↑ keyを優先してソート

$ echo '[{"a":3}, {"a":2}, {"a":1}]' | ./sort_json.rb
[
  {
    "a": 1
  },
  {
    "a": 2
  },
  {
    "a": 3
  }
]
↑ keyが同じなら値でソート

$ echo '[{"a":1, "c":1}, {"b":[{"x":"z"},{"x":9}], "a":1}, {"a":1}]' | ./sort_json.rb
[
  {
    "a": 1
  },
  {
    "a": 1,
    "b": [
      {
        "x": 9
      },
      {
        "x": "z"
      }
    ]
  },
  {
    "a": 1,
    "c": 1
  }
]
↑ keyが有ったり無かったりの複合

<AWS CLIでの例>

$ aws ec2 describe-security-groups --output json | <パス>/sort_json.rb > security-groups.json

<参考にした記事>
RubyでJSONを扱うときに便利な関数まとめ

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0