jq 1.7の新機能ーキー連鎖時の . と [] の用法

[JSON](https://datatracker.ietf.org/doc/html/rfc8259)処理のコマンドラインツールである[`jq`](https://stedolan.github.io/jq/)が、5年ぶりにアップデートしました。現在の最新は1.7.1（2023年12月リリース）です。1.6からいろいろと改定や新機能の追加があって、ますます楽しくなっています。

全容は[Github上のリリースノート](https://github.com/jqlang/jq/releases)を見ていただくとして、今日はネストされた構造型データ（オブジェクトおよび配列）のツリーを下って値を抽出するときの`.`と`[]`についてです。

次のように、2重にネストされたJSONオブジェクトを考えます（環境変数`DON`に収容されているとします）。

```bash
$ DON='{"どんぶり": {"かつ": 600, "親子": 550}}'
$ echo $DON | jq '.'
{
  "どんぶり": {
    "かつ": 600,
    "親子": 550
  }
}
```

### これまでは

ネストされたオブジェクトの値にアクセスするには、プロパティキーをドット`.`でつなぎます。マニュアルはこの記法を「オブジェクト識別子インデックス」と呼んでいます（object identifier-index）。上記の数値（かつ丼の値段）を取得するには次のようにします。

```bash
$ jq-1.6 --version                          # 1つ前の1.6を使います
jq-1.6

$ echo $DON | jq-1.6 '."どんぶり"."かつ"'
600
```

英数文字なら`.donburi.katsu`のように書けますが、それ以外のUTF-8文字では二重引用符`"`でくくらなければならないところがポイントです。

`[]`でキーをくくった記法も使えます。オブジェクトインデックスです（object index）。

```bash
$ echo $DON | jq-1.6 '.["どんぶり"]["親子"]'
550
```

ただし、`[]`と`.`は混ぜては使えません。

```bash
$ echo $DON | jq-1.6 '.["どんぶり"].["親子"]'  # 混ぜるな危険
jq: error: syntax error, unexpected '[', expecting FORMAT or 
	QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.["どんぶり"].["親子"]
jq: 1 compile error
```


### JavaScriptでは

他の言語系でも事情は同様です。Node.jsで試してみると、やはり混ぜてはダメです。

```bash
$ node
Welcome to Node.js v20.9.0.
Type ".help" for more information.

# ドットチェーン
> JSON.parse('{"どんぶり": {"かつ": 600, "親子": 550}}').どんぶり.親子
550

# 角括弧記法
> JSON.parse('{"どんぶり": {"かつ": 600, "親子": 550}}')["どんぶり"]["親子"]
550

# 混ぜるな危険
> JSON.parse('{"どんぶり": {"かつ": 600, "親子": 550}}').["どんぶり"].["親子"]
JSON.parse('{"どんぶり": {"かつ": 600, "親子": 550}}').["どんぶり"].["親子"]
                                               ^
Uncaught SyntaxError: Unexpected token '[
```

### これからは

`.`と`[]`を混ぜた記法も認められます。

```bash
$ jq --version
jq-1.7.1                                    # 1.7です

$ echo $DON | jq '.["どんぶり"].["親子"]'      # 混ぜてもOK
550

$ echo $DON | jq '."どんぶり".["親子"]'        # 一方だけもあり
550

$ echo $DON | jq '.["どんぶり"]."親子"'        # ditto。今度は反対側
550
```


### おわりに

他の言語で慣れていれば混用ミスなどありえない、と思うかもしれませんが、`jq`ではやっちゃったりすることもあります。

というのも、パイプを使うときは、その時点のツリー上の位置を参照するのに`.`が必要だからです。

```bash
$ echo $DON | jq-1.6 '.["どんぶり"] | .["かつ"]'
600
```

そのため、パイプを整理するときに`.`を消し忘れたり、逆に、`.`の連鎖だと読みにくいからとパイプを挟んだりと、フィルタをいじっていると、ミスをしがちです。単純にパイプを挟んだり消したりしても動作するようになったのは、その点、ありがたいものです。

1.7では、他にも、細かいところで性能向上も図られています。まだ1.6をお使いなら、これを機会に1.7にアップグレードしましょう。



### 参考

- [./jq](https://stedolan.github.io/jq/) ... `jq`のオフィシャルサイトです（英文）。
- [Github jqland/jq Releases](https://github.com/jqlang/jq/releases) ... `jq`のリリースノートです（英文）。
- 『[jqハンドブック](http://www.cutt.co.jp/book/978-4-87783-491-3.html)』（2021）... フィルタの基本である値の指示は、この本の第1章で詳しく説明しています。ご購入はこちらから【[出版社](http://www.cutt.co.jp/book/978-4-87783-491-3.html) | [honto](https://honto.jp/netstore/pd-book_31037910.html) | [amazon.co.jp](https://www.amazon.co.jp/jq/dp/4877834915) | [ヨドバシカメラ](https://www.yodobashi.com/product/100000009003450000/)】。
- 「[jqのむだづかい](https://qiita.com/stoyosawa)」 ... `jq`ではまずやろうとは思わない処理の探求記録です。完成版は他の（通常機能な）レシピとともに『[jqクックブック](https://www.cutt.co.jp/book/978-4-87783-508-8.html)』（2023）に掲載しました。ご購入はこちらから【[出版社](https://www.cutt.co.jp/book/978-4-87783-508-8.html) | [honto](https://honto.jp/netstore/pd-book_32427461.html) | [amazon.co.jp](https://www.amazon.co.jp/dp/4877835083) | [ヨドバシカメラ](https://www.yodobashi.com/product/100000009003710680/)】。

<img src="http://www.cutt.co.jp/book/images/978-4-87783-491-3.png" width="200" alt="表紙"></img> <img src="https://www.cutt.co.jp/book/images/978-4-87783-508-8.png" width="200" alt="表紙"></img>