コメント書けるJSON `jsonc`(JSON with Comments) とは

# jsoncとは

jsonc... それはコメントを書けるjson形式。
でもjsonにコメントを書きたいなんて誰でも考えることだし、できなくても何とかなるものだしで、結局フワフワした感じになっています。

## Microsoftのjsonc

調べて一番に出てくるのはコレ、Microsoftのjsでの実装。

https://github.com/Microsoft/node-jsonc-parser

VSCodeのドキュメントでは`JSON with Comments`と呼んでいます。

https://code.visualstudio.com/docs/languages/json#_json-with-comments

ざっくり和訳↓
> 通常のJSONモードに加えて、JSON with Comments (jsonc)モードも提供します。
> これはVSCodeの設定ファイル(settings.json, tasks.json, or launch.json)にも使用されます。
> 
> このモードでは、JavaScriptのように、ブロックコメント(/* */)および、一行コメント(//)を使用できます。
> (末尾のカンマも許容しますが推奨しないしワーニングを出します)

つまりMicrosoftが言うには、`//～`と`/*～*/`をコメントとして、末尾カンマは無いものとして見るだけのjsonですよと。
そして、拡張子は`.json`そのまま使っちゃったりしますよと。

`settings.json`を開いてみると、ほんとだ...
![2024-02-08_21h32_22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488658/a7a61b7e-b721-f2ca-8847-a42e0e0c1c9d.jpeg)

ちなみに自前のjsonファイルは普通に開いてコメントを書くと、シンタックスハイライトで怒られる。formatterを変更してあげなきゃならない。
拡張子を`.jsonc`とすると、デフォルトでシンタックスハイライトが付くしFormatも効く。

![2024-02-08_20h47_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488658/aea9c163-e0b2-ab4d-2085-34b14e358ff0.jpeg)

## 別のjsonc

### Microsoftを踏襲したGOでの実装

githubで検索すると出てくる、このGOでの実装はMicrosofを踏襲してる。

https://github.com/muhammadmuzzammil1998/jsonc

### オリジナルな実装のjsoncプロジェクト

このプロジェクトは、コメントも書けるし、要素をクォーテーション`""`で囲わなくてもいい。
`""`で囲ったときは改行を`\n`に変換してくれる。より親切なGOでの実装。

これはたまたま名前が`jsonc`なだけで、Microsoftの`jsonc`とは別の`jsonc`:upside_down:

> Jsonc is a simplified json format which allows comments and unquoted values delimited by whitespace. A jsonc formatted file can be unambiguously transformed to a json file. Comments will be stripped out and quotes added.

https://github.com/komkom/jsonc

### Qiitaのエディタでは

Qiitaのマークダウンエディタ内のコードブロックでは、`jsonc`が`json-doc`という言語のエイリアスになっている。
一行コメントは受け入れてくれるけどブロックコメントはコメント扱いしてくれない。
これもまた別のものらしい。

![2024-02-08_22h14_57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488658/35772505-b44c-ce39-309e-37ee1be9ec20.jpeg)

## I'm not sure "jsonc" is an official thing

`highlight.js`のissueで面白い議論があった。
「jsoncって別に正式なものじゃないよね」「`highlight.js`としては拡張子は気にせず、`.json`ファイルにコメントがあったら処理する、ってスタンスでいく」みたいな話をしている。

https://github.com/highlightjs/highlight.js/issues/2016

## 結局`jsonc`とは

Microsoftスタイルを踏襲しつつ、まとめると次の感じだと思います。

* javascriptと似たコメント
    * // 一行コメント
    * /* ブロックコメント */
* 末尾カンマを許す
    * 増えるリスト系とgitの相性がいいね
    * でもVSCodeのフォーマッターには消される
* jsoncは呼び名であって拡張子ってわけではない
    * 拡張子にしてもいい
* そもそも正式なものではない
    * 実装する人の匙加減かも

## Pythonでjsoncを読む実装

コメントは完全に読み捨てるやり方。

まずjsoncなファイルを準備して

```jsonc:prams.jsonc
// 設定ファイル prams.jsonc
// これと
/*
    これをコメントとして扱える

    あとはjsonのフォーマットに従って書く
*/
{
  "HOGE": {
    // boolな設定
    "fuga": true,
    // リストな設定
    "size": [480, 320], // デフォルトを書いたりなど
    // 文字列な設定
    "name": "JSON with Comments"
  }
}
```

`//～`と`/*～*/`を除去して`json.loads()`するだけの実装。
末尾カンマは、VSCodeが消してくれるからいいや。

```python:jsonc_reader.py
import re
import json

JS_COMMENT_PATTERN = R"/\*[\s\S]*?\*/|//.*"


def read_str(_text: str) -> dict:
    """jsonc文字列を辞書にします
    """
    sub_text = re.sub(JS_COMMENT_PATTERN, '', _text)
    return json.loads(sub_text)


def read_file(_filepath: str, _encoding: str = "utf-8") -> dict:
    """jsonc形式ファイルを辞書にします
    """
    with open(_filepath, 'r', encoding=_encoding) as f:
        text = f.read()
    return read_str(text)


if __name__ == "__main__":
    print(read_file(r"params.jsonc"))

# $ python .\jsonc.py
# -> {'HOGE': {'fuga': True, 'size': [480, 320], 'name': 'JSON with Comments'}}
```