Site logo
devhx2.blog

JSON の派生フォーマットたち

はじめに

最近 JSONP(詳細は後述します)というものに触れる機会がありました。 VSCode の設定ファイルで使われる JSONC は知っていたのですが、他にも派生のフォーマットもあるんだと知りました。 ということで、他にもっとないか個人的な興味から調べてまとめました。

そもそも JSON って

JavaScript Object Notation の略で、データを表現するためのテキスト形式です。

json
{
  "name": "John Doe",
  "age": 30,
  "city": "New York"
}

こんな感じでキーと値のペアでデータを表現します。

なぜ普及したのか?

人間にとって比較的読み書きしやすく、機械にとってもパース・生成が簡単に行えます。 また、JavaScript のオブジェクト記法が由来のため、C系の言語との親和性が高いです。 そのため、多くの言語の標準機能で実装されており、APIのレスポンス、設定ファイルなどでよく使われています。

なぜ派生するのか?

扱いやすく、多くの言語で実装されている JSON でも弱点はあります。

上記のような制約があるため、手での書き心地は微妙で、データフォーマットの網羅性も足りません。 多くのケースで有用であるが、ところどころ適さないって感じですね。

テキスト系

まずは、テキストとして人間寄りに派生したフォーマットを紹介します。

JSON5

JSON5 は制約を緩和するために提案された拡張フォーマットで、ECMAScript 5.1 の構文を一部取り込んだ JSON のスーパーセットです。(5 の由来は ECMAScript 5.1 、通称 ES5 だと個人的に推測。) JSON にない以下の機能が使えます。

json5
{
  // コメントが書ける
  name: 'my-app',       // キーに引用符不要
  version: 2.0,
  port: 0x1F90,         // 16進数もOK
  features: [
    "hoge \             // 複数行文字列
huga\\n",               // エスケープ
    'piyo',         // 末尾カンマOK
  ],
}

Babel の設定ファイルは babel.config.json ですが、JSON5 として解析されるほか、ESLint の公式プラグイン @eslint/json では JSON 以外に JSON5 も対象にできます。

JSON5 公式ドキュメント

Babel 公式ドキュメント

@eslint/json - GitHub

JSONC

JSON with Comments の略で、JSONにコメントを追加できるようにした拡張フォーマットです。 VSCode の設定ファイル settings.json で使われているので、よく目にすると思います。 ただ、VSCode 内でのローカルルールみたいな感じで詳細な仕様は存在しないようです。 こちらも @eslint/json で扱えるようです。

バイナリ系

次は、バイナリ形式にして小サイズに特化した派生フォーマットです。

BSON

Binary JSON の略で、JSON を拡張したバイナリ形式のデータ交換フォーマットです。 MongoDB のためのフォーマットのため、ほぼすべての主要なバックエンドの言語では扱うことができます。 ただし、MongoDB のドライバが裏で自動的に BSON に変換しているため、普段開発者が意識することはないです。 BSONは3つの特性を持つよう設計されています。

  1. ネットワーク経由が前提のためサイズが軽量
  2. トラバースが容易
  3. エンコード・デコードが効率的

(ただし、長さのプレフィックスや配列インデックスが付くため、場合によっては JSON よりサイズが大きくなることもあります。)

また、JSON には無い型(日付型・バイト配列・IEEE 754準拠の浮動小数点など)を持ち、厳密な型指定ができます。

BSON 公式ドキュメント

MessagePack

JSON から徹底的に無駄を削ぎ落として、省サイズ・高速転送に特化したものです。 「It’s like JSON. but fast and small.」を謳っており、ネットワーク転送やストレージ効率を重視する場面で使われます。

JSON との互換性が高く、JSON で表現できるデータはそのまま MessagePack に変換できます。 ただし、BSON のような拡張型(日付型・バイナリ型など)は標準では持たず、あくまで JSON の型体系をコンパクトにしたものです。 主な用途として、ログ転送、リアルタイム通信(ゲームや IoT)などがあります。多くの言語で公式・非公式のライブラリが提供されており、導入しやすいのも特徴です。

MessagePack 公式ドキュメント

ハック系

最後は、特定の課題をハックするために派生したフォーマットです。

JSONP

JSON with Padding の略で、CORS問題を回避するために JSON をコールバック関数でラップして返す手法です。 CORS が普及する前の苦肉の策のため 現在ではセキュリティの観点から非推奨 です。

js
callback({
  "name": "John Doe",
  "age": 30,
  "city": "New York"
})

ブラウザには同一オリジンポリシーがあり、異なるドメインへの Ajax 通信が制限されています。 しかし、script タグなら異なるドメインでも読み込めるため、この問題を回避できます。

html
<!-- バックが対応していたら callback 名を指定可能 -->
<script src="https://api.example.com/data?callback=myFunc"></script>

CORS(Cross-Origin Resource Sharing)がブラウザに実装され、サーバー側でヘッダーを設定するだけで安全にクロスオリジン通信ができるようになったため、JSONP は完全に不要になりました。

JSONL

JSON Lines の略で、1行に付き1つのオブジェクトを書くフォーマットです。 以下の例を見ればすぐにわかります。

jsonl
{"id": 1, "name": "Alice", "age": 25}
{"id": 2, "name": "Bob", "age": 30}
{"id": 3, "name": "Charlie", "age": 22}

オブジェクトの区切りは改行で、配列 [] でまとめる必要はありません。 通常の JSON はパース処理の前に全体読み込みが必要ですが、 JSONL は 1行ずつ読み込みができます。 なので、巨大なファイルであっても CSV のように先頭から順次処理できます。 また、最後尾へのオブジェクト追加もファイルの最後に追記するだけです。

JSONL 公式ドキュメント