Help us understand the problem. What is going on with this article?

jqコマンドでJSONからキー名をいい感じに取得する

下記記事を参考にほぼほぼやりたいことはできたのですが、ハマったのでメモ。

[jq] JSONデータの特定階層にあるキー名のユニーク値を取得 - Qiita
https://qiita.com/withelmo/items/b0e1ffba639dd3ae18c0

JSONファイル

行ごとにキーが同じだったり、違ったり、数も違うちょっと困ったJSONファイルがあるときに使えます。

hoge.json
{"hoge1": "hoge", "hoge2": 2, "hoge3": false}
{"hoge2": "hoge", "hoge3": 2, "hoge4": false, "hoge5": "FOO"}
{"hoge1": "hoge", "hoge2": 2, "hoge6": false}

いい感じのコマンド

> cat hoge.json | jq -s -r '[ .[] | keys ] | flatten | unique | .[]'

hoge1
hoge2
hoge3
hoge4
hoge5
hoge6

jq-s オプションで配列にする

ファイル中に{...}{...}{...}[] 括りされず、, 区切りもないため、jq--slurp (-s )オプションで配列に放り込みます。

jq Manual (development version)
https://stedolan.github.io/jq/manual/

--slurp/-s:

Instead of running the filter for each JSON object in the input, read the entire input stream into a large array and run the filter just once.

(Google翻訳)入力内の各JSONオブジェクトに対してフィルターを実行する代わりに、入力ストリーム全体を大きな配列に読み取り、フィルターを1回だけ実行します。

# -s オプションなし
> cat hoge.json | jq

{
  "hoge1": "hoge",
  "hoge2": 2,
  "hoge3": false
}
{
  "hoge2": "hoge",
  "hoge3": 2,
  "hoge4": false,
  "hoge5": "FOO"
}
{
  "hoge1": "hoge",
  "hoge2": 2,
  "hoge6": false
}


# -s オプションあり
> cat hoge.json | jq -s

[
  {
    "hoge1": "hoge",
    "hoge2": 2,
    "hoge3": false
  },
  {
    "hoge2": "hoge",
    "hoge3": 2,
    "hoge4": false,
    "hoge5": "FOO"
  },
  {
    "hoge1": "hoge",
    "hoge2": 2,
    "hoge6": false
  }
]

キー名だけ出力する

あとは上記記事と同じく[ .[] | keys ] | flatten | unique でキー名を取得、平坦化して重複を取り除きます。
ちなみに平坦化しないとこんな感じになります。unique が効きません。

> cat hoge.json  | jq -s -r '[ .[] | keys ] | unique'
[
  [
    "hoge1",
    "hoge2",
    "hoge3"
  ],
  [
    "hoge1",
    "hoge2",
    "hoge6"
  ],
  [
    "hoge2",
    "hoge3",
    "hoge4",
    "hoge5"
  ]
]

最後に.[] で出力し、jq コマンドの--raw-output (-r )オプションでダブルクォーテーションを取り除きます。

jq Manual (development version)
https://stedolan.github.io/jq/manual/

--raw-output / -r:

With this option, if the filter’s result is a string then it will be written directly to standard output rather than being formatted as a JSON string with quotes. This can be useful for making jq filters talk to non-JSON-based systems.

(Google翻訳)このオプションを使用すると、フィルターの結果が文字列の場合、引用符付きのJSON文字列としてフォーマットされるのではなく、標準出力に直接書き込まれます。 これは、jqフィルターが非JSONベースのシステムと通信するのに役立ちます。

最後を.[] としないと以下のようになり、-r オプションは働きません。

> cat hoge.json | jq -s -r '[ .[] | keys ] | flatten | unique'

[
  "hoge1",
  "hoge2",
  "hoge3",
  "hoge4",
  "hoge5",
  "hoge6"
]

jq コマンドは奥が深いなぁ。

おまけ

Google翻訳さんによるとslurp丸lurみ だそうですw
ヌードルハラスメント的ななにかが働いているのでしょうか???

スクリーンショット 2019-11-27 16.32.36.png

参考

[jq] JSONデータの特定階層にあるキー名のユニーク値を取得 - Qiita
https://qiita.com/withelmo/items/b0e1ffba639dd3ae18c0

jq Manual (development version)
https://stedolan.github.io/jq/manual/

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away