JSON完全に理解した?現場で恥をかかないデータ設計7つの鉄則

代のWeb開発において、JSON (JavaScript Object Notation) を扱わない日は一日たりとも存在しません。APIレスポンス、設定ファイル、ログデータ、NoSQL...。あらゆる場所にJSONは存在します。しかし、あなたは本当にJSONを「正しく」使いこなせていると言い切れるでしょうか?

「ただのテキストデータだろう」と高を括っていると、本番環境で予期せぬパースエラーや、セキュリティホール、あるいはパフォーマンスのボトルネックを引き起こす原因になります。この記事では、教科書的な定義だけでなく、シニアエンジニアが現場で実践している「堅牢で扱いやすいJSON設計」のノウハウを、失敗事例を交えて徹底的に解説します。明日からのコード品質を一段階引き上げる準備はいいですか?

なぜXMLは敗れ、JSONが覇権を握ったのか

歴史を振り返ると、かつてデータ交換の王者はXMLでした。しかし、XMLは「冗長」で「解析が重い」という致命的な課題を抱えていました。タグの開始と終了でデータを囲む必要があり、ファイルサイズが肥大化しやすかったのです。

歴史的背景: 2000年代初頭、Douglas Crockford氏によって提唱されたJSONは、JavaScriptのオブジェクトリテラル構文の一部をベースにしています。これにより、ブラウザ標準のJSエンジンで爆速でパースできるという、当時としては革命的な利点を持っていました。

現在の開発現場において、JSONが選ばれる理由は明確です。

  • 圧倒的な可読性: 人間が見て直感的に構造を理解できる。
  • 言語非依存: JavaScriptだけでなく、Python, Go, Javaなど全ての主要言語に標準ライブラリが存在する。
  • 軽量: 無駄なメタデータが少なく、ネットワーク帯域を圧迫しない。

JSON構文:プロが意識する「厳格なルール」

JSONは「JavaScriptのオブジェクト」に似ていますが、完全に別物です。ここを混同するとエラーの温床になります。特に以下のルールは絶対です。

1. キーは必ずダブルクォーテーションで囲む

JavaScriptでは { name: "Taro" } と書けますが、JSONでは Syntax Error です。必ず { "name": "Taro" } と記述しなければなりません。シングルクォーテーション ' も使用不可です。

2. 末尾のカンマ(Trailing Comma)は禁止

配列やオブジェクトの最後の要素の後にカンマを残すことは、モダンなJavaScriptでは許容されていますが、JSON仕様では厳密に禁止されています。古いブラウザや一部の厳格なパーサー(JavaのJacksonなど)は、これで即座にクラッシュします。

よくあるミス: 設定ファイルなどを手動で編集した際、行を削除して末尾カンマを残してしまい、アプリが起動しなくなるケースが後を絶ちません。エディタのLinter機能を有効にして防ぎましょう。

利用可能なデータ型と「使えない」型

JSONで扱えるのは以下の6つだけです。

  1. 文字列 (String)
  2. 数値 (Number): 整数・浮動小数点の区別なし
  3. 真偽値 (Boolean): true / false (小文字のみ)
  4. 配列 (Array)
  5. オブジェクト (Object)
  6. null

ここで重要なのは「何が使えないか」を知っておくことです。undefined、関数、Symbol、そして何より日付 (Date) はJSONで直接表現できません。

JavaScriptでの実装と「隠れた機能」

基本の JSON.parse()JSON.stringify() は誰もが使いますが、第2引数、第3引数まで使いこなしているエンジニアは意外と少ないものです。

デバッグ効率を上げる JSON.stringify の整形

ログ出力や設定ファイルの保存時、一行に圧縮されたJSONは読みづらいですよね。第3引数にスペースの数を渡すことで、綺麗に整形(Pretty Print)できます。

const user = {
  id: 101,
  name: "Suzuki",
  roles: ["admin", "editor"]
};

// 第3引数に '2' を指定すると、インデント2つで整形される
const prettyJson = JSON.stringify(user, null, 2);

console.log(prettyJson);
/* 出力:
{
  "id": 101,
  "name": "Suzuki",
  "roles": [
    "admin",
    "editor"
  ]
}
*/

安全なパース処理(例外ハンドリング)

外部APIからのレスポンスや、ローカルストレージの値をパースする際、JSON.parse() を裸で使うのは自殺行為です。不正な文字列が渡されると即座にアプリがクラッシュします。

// ❌ 危険なコード
const data = JSON.parse(apiResponse); 

// ✅ 推奨されるラッパー関数の例
function safeParse(jsonString, fallbackValue) {
  try {
    return JSON.parse(jsonString);
  } catch (error) {
    console.error("JSON Parse Error:", error);
    return fallbackValue; // デフォルト値を返すことでアプリの停止を防ぐ
  }
}

シニアが注意する3つの「落とし穴」

実務レベルでJSONを扱う際、以下の問題に直面することが必ずあります。これらを知っているかどうかが、ジュニアとシニアの分水嶺です。

1. Date型喪失問題

JSONには日付型がありません。JSON.stringify() すると、Dateオブジェクトは ISO 8601 形式の文字列(例: "2023-10-27T10:00:00.000Z")に変換されます。これを受け取って parse しても、それはただの「文字列」です。

対策: 受信側で明示的に new Date(dateString) を通してDateオブジェクトに復元する必要があります。あるいは、日付サフィックス(例: createdAt_date)をキー名につけて、ミドルウェアで自動変換する設計を採用する場合もあります。

2. BigIntと精度の壁

近年のJavaScriptには巨大な整数を扱う BigInt がありますが、JSONはこれをサポートしていません。無理やりstringifyするとエラーになります。また、APIから巨大な数値(64bit整数など)が送られてきた場合、JavaScriptの Number 型の精度限界(2^53 - 1)を超え、勝手に丸められてしまうリスクがあります。

解決策: Twitter APIのように、巨大なIDは数値ではなく文字列(String)として送受信するのが鉄則です。

3. コメントが書けないジレンマ

標準のJSONにはコメントが書けません。これが設定ファイルとして使う際の最大の弱点です。「なぜこの設定値なのか」を残せないからです。VS Codeの設定ファイルなどが採用している「JSON with Comments (JSONC)」や「JSON5」の使用を検討するか、コメント専用のキー(例: "_comment": "この値は...")を含めるなどの工夫が必要です。

ベストプラクティスとエコシステム

最後に、堅牢なシステムを構築するためのツールと設計思想を紹介します。

JSON Schemaによるバリデーション

APIドキュメントと実装が乖離することは日常茶飯事です。これを防ぐために「JSON Schema」を導入しましょう。期待されるデータ構造を定義し、自動テストでバリデーションを行うことで、クライアントとサーバー間の契約を守ることができます。

項目 説明 ツール例
型定義 データの型や必須項目を厳密に定義 TypeScript, QuickType
バリデーション ランタイムでのデータ検証 Ajv, Zod
フォーマッター コードスタイルの統一 Prettier

特にTypeScript環境では、Zodのようなライブラリを使って、ランタイムのバリデーションと静的な型定義を一本化するのがトレンドです。

セキュリティ対策:JSON HijackingとXSS

信頼できないソースからのJSONを扱う際、eval() を使うのは論外です。また、HTMLの中にJSONを埋め込む場合(SSR時の初期状態データなど)、</script> という文字列が含まれているとXSS攻撃の足がかりになります。必ず適切なエスケープ処理を行うライブラリやフレームワークの機能を使用してください。

まとめ:JSONを制する者はデータを制す

JSONはシンプルがゆえに奥が深く、その扱い方一つでアプリケーションの品質が大きく変わります。型のない柔軟さに甘えることなく、スキーマ定義やエラーハンドリングを徹底することで、初めて「堅牢なシステム」と呼べるものが出来上がります。

今日紹介したテクニックを、ぜひ次のプルリクエストに取り入れてみてください。あなたのコードに対する信頼度が、確実に上がるはずです。

Post a Comment