jsoncとは
jsonc... それはコメントを書けるjson形式。
でもjsonにコメントを書きたいなんて誰でも考えることだし、できなくても何とかなるものだしで、結局フワフワした感じになっています。
Microsoftのjsonc
調べて一番に出てくるのはコレ、Microsoftのjsでの実装。
VSCodeのドキュメントではJSON with Commentsと呼んでいます。
ざっくり和訳↓
通常のJSONモードに加えて、JSON with Comments (jsonc)モードも提供します。
これはVSCodeの設定ファイル(settings.json, tasks.json, or launch.json)にも使用されます。このモードでは、JavaScriptのように、ブロックコメント(/* */)および、一行コメント(//)を使用できます。
(末尾のカンマも許容しますが推奨しないしワーニングを出します)
つまりMicrosoftが言うには、//~と/*~*/をコメントとして、末尾カンマは無いものとして見るだけのjsonですよと。
そして、拡張子は.jsonそのまま使っちゃったりしますよと。
ちなみに自前のjsonファイルは普通に開いてコメントを書くと、シンタックスハイライトで怒られる。formatterを変更してあげなきゃならない。
拡張子を.jsoncとすると、デフォルトでシンタックスハイライトが付くしFormatも効く。
別のjsonc
Microsoftを踏襲したGOでの実装
githubで検索すると出てくる、このGOでの実装はMicrosofを踏襲してる。
オリジナルな実装のjsoncプロジェクト
このプロジェクトは、コメントも書けるし、要素をクォーテーション""で囲わなくてもいい。
""で囲ったときは改行を\nに変換してくれる。より親切なGOでの実装。
これはたまたま名前がjsoncなだけで、Microsoftのjsoncとは別のjsonc![]()
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.
Qiitaのエディタでは
Qiitaのマークダウンエディタ内のコードブロックでは、jsoncがjson-docという言語のエイリアスになっている。
一行コメントは受け入れてくれるけどブロックコメントはコメント扱いしてくれない。
これもまた別のものらしい。
I'm not sure "jsonc" is an official thing
highlight.jsのissueで面白い議論があった。
「jsoncって別に正式なものじゃないよね」「highlight.jsとしては拡張子は気にせず、.jsonファイルにコメントがあったら処理する、ってスタンスでいく」みたいな話をしている。
結局jsoncとは
Microsoftスタイルを踏襲しつつ、まとめると次の感じだと思います。
- javascriptと似たコメント
- // 一行コメント
- /* ブロックコメント */
- 末尾カンマを許す
- 増えるリスト系とgitの相性がいいね
- でもVSCodeのフォーマッターには消される
- jsoncは呼び名であって拡張子ってわけではない
- 拡張子にしてもいい
- そもそも正式なものではない
- 実装する人の匙加減かも
Pythonでjsoncを読む実装
コメントは完全に読み捨てるやり方。
まずjsoncなファイルを準備して
// 設定ファイル prams.jsonc
// これと
/*
これをコメントとして扱える
あとはjsonのフォーマットに従って書く
*/
{
"HOGE": {
// boolな設定
"fuga": true,
// リストな設定
"size": [480, 320], // デフォルトを書いたりなど
// 文字列な設定
"name": "JSON with Comments"
}
}
//~と/*~*/を除去してjson.loads()するだけの実装。
末尾カンマは、VSCodeが消してくれるからいいや。
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'}}


