- JavaScriptで JSONを使う方法、parse() によるdecode/ stringify()によるencodeの使い方を解説|Javascript入門講座(15)のPodcast
- はじめに
- JSONの基本構造とJavaScriptオブジェクトとの決定的な違い
- JSON.stringify() によるエンコードの仕組み
- JSON.parse() によるデコードの仕組み
- 数値精度の限界と最新の解決策:context.source
- 循環参照の検知と回避策
- JSON.rawJSON() と数値のロスレス・シリアライズ
- ウェブ開発の現場で使われるJSONの実践例
- JSONモジュールのネイティブサポート (Baseline 2025)
- セキュリティとパフォーマンスの考慮事項
- まとめ
- 参考資料
JavaScriptで JSONを使う方法、parse() によるdecode/ stringify()によるencodeの使い方を解説|Javascript入門講座(15)のPodcast
下記のPodcastは、Geminiで作成しました。
はじめに
現代のウェブ開発におけるJSONの役割とその進化現代のプログラミング環境において、JSON(JavaScript Object Notation)は単なるデータ形式の枠を超え、システム間を繋ぐ標準言語としての地位を確立しています。もともとはJavaScriptのオブジェクトリテラル構文をベースに誕生しましたが、そのシンプルさと軽量性から、現在ではプログラミング言語の種類を問わず、API通信や設定ファイルの記述に不可欠な存在となっています 。JavaScriptの標準仕様であるECMAScriptにおいても、JSONを扱うための仕組みは日々進化を続けています。かつては外部ライブラリを必要としていた処理も、現在ではグローバルな JSON オブジェクトを通じて、より安全かつ高度に実行できるようになりました 。本稿では、基本的な JSON.parse() によるデコードと JSON.stringify() によるエンコードの仕組みを軸に、最新のES2024・ES2025仕様で導入された context.source や JSON.rawJSON()、さらには最新ブラウザの標準機能となったJSONモジュールまで、初心者の方にも分かりやすく丁寧に解説します。
JSONの基本構造とJavaScriptオブジェクトとの決定的な違い
JSONはJavaScriptの書き方を模していますが、データ交換の厳密性を保つために、JavaScriptよりも厳しいルールが設けられています 。この違いを正確に理解することが、パースエラー(解析エラー)を防ぐ第一歩となります。
JSONがサポートするデータ型
JSONで扱うことができるデータは、以下の6つの型に限定されています 。
| データ型 | 内容 | 例 |
|---|---|---|
| 文字列 (String) | 必ずダブルクォートで囲む | "こんにちは" |
| 数値 (Number) | 整数、浮動小数点。NaNやInfinityは不可 | 100, -0.5 |
| 真偽値 (Boolean) | true または false | true |
| ヌル値 (Null) | 値が空であることを示す | null |
| オブジェクト (Object) | キーと値のペア。キーは必ず文字列 | {"id": 1} |
| 配列 (Array) | 値の順序付きリスト | `` |
JavaScriptオブジェクトとの相違点と注意点
初心者が最も間違いやすいポイントは、引用符の扱いと末尾のカンマです 。
引用符の厳格な使用: JSONでは、オブジェクトのキー(プロパティ名)および文字列の値は、必ずダブルクォート(")で囲まなければなりません。JavaScriptでは許可されるシングルクォート(')や引用符なしのキーは、JSONでは不正な形式とみなされます 。
末尾のカンマの禁止: 配列やオブジェクトの最後の要素の後にカンマを置くことはできません。これは、JavaScriptの新しい仕様では許容されていますが、JSONでは構文エラーとなります 。
数値の表記制限: 数値の先頭に不要なゼロを付けること(例:0123)や、小数点から書き始めること(例:.5)は禁止されています 。
コメントの不可: JSONファイル内には、// や /* */ といったコメントを記述することはできません 。


JSON.stringify() によるエンコードの仕組み
JavaScriptのオブジェクトや配列を、ネットワーク送信や保存が可能な「JSON文字列」に変換することをエンコード(またはシリアライズ)と呼びます。これを行うのが JSON.stringify() 静的メソッドです 。
基本的な使い方
最も単純な使い方は、変換したい値を第1引数に渡すだけです。
javascript
const user = {
id: 7,
name: "山田太郎",
hobbies: ["読書", "開発"]
};
const jsonString = JSON.stringify(user);
console.log(jsonString); // '{"id":7,"name":"山田太郎","hobbies":["読書","開発"]}'変換時の特殊な挙動
JSON.stringify() は、特定のJavaScript固有の値を変換する際、以下のような自動調整を行います 。
undefined、関数、Symbol: これらがオブジェクトのプロパティに含まれている場合、変換後のJSONからは完全に削除されます。配列の要素として含まれている場合は、構造を維持するために null に置き換わります 。
NaN、Infinity: これらはJSONでは表現できないため、一律で null に変換されます 。
Date オブジェクト: 自動的に toISOString() メソッドが呼び出され、"2026-02-15T00:00:00.000Z" のような日時文字列に変換されます 。
高度なオプション:replacerとspace
JSON.stringify() には、出力を詳細にカスタマイズするための第2、第3引数が用意されています 。
第2引数の replacer にプロパティ名の配列を渡すと、その項目だけを抽出したJSONを作成できます。また、関数を渡すことで、特定の値を加工しながら変換することも可能です 。
第3引数の space を使用すると、インデントを追加して「人間が読みやすい形式」で出力できます。数値を渡すとその数分のスペースが、文字列("\t"など)を渡すとその文字がインデントとして使用されます 。
javascript
const data = { id: 101, secret: "password123", active: true };
// secretを除外し、2スペースで整形
const result = JSON.stringify(data, (key, value) => {
if (key === "secret") return undefined;
return value;
}, 2);
/*
出力結果:
{
"id": 101,
"active": true
}
*/

JSON.parse() によるデコードの仕組み
受信したJSON文字列を、JavaScriptプログラムで操作可能なオブジェクトや配列に復元することをデコード(またはデシリアライズ)と呼びます。これには JSON.parse() 静的メソッドを使用します 。
基本的な使い方とエラーハンドリング
JSON.parse() は引数に文字列を受け取り、その内容に基づいたJavaScriptの値を返します 。
javascript
const json = '{"status": "ok", "code": 200}';
const obj = JSON.parse(json);
console.log(obj.status); // "ok"重要な注意点として、渡された文字列が正しいJSON形式でない場合、このメソッドは即座に SyntaxError を投げます 。実務では、アプリがクラッシュするのを防ぐために try...catch 構文で囲むのが一般的です 。
reviver関数による値の復元
JSON.parse() の第2引数には、解析後の各値を加工するための reviver 関数を渡すことができます 。これは、JSON.stringify() で文字列化されてしまった Date オブジェクトなどを元の型に戻す際に非常に便利です。
解析処理は「ボトムアップ(下から上へ)」の順序で行われます。つまり、最も深くネストされたプロパティから順に reviver が呼び出され、最後にルートオブジェクトに対して呼び出されます 。
javascript
const logJson = '{"event": "login", "time": "2026-02-15T12:00:00Z"}';
const log = JSON.parse(logJson, (key, value) => {
if (key === "time") {
return new Date(value); // 日時文字列をDateオブジェクトに変換
}
return value;
});
console.log(log.time.getFullYear()); // 2026数値精度の限界と最新の解決策:context.source
JavaScriptには「巨大な数値を正確に扱えない」という長年の課題がありました。JavaScriptの通常の数値型(Number)は、IEEE 754倍精度浮動小数点数という形式を採用しており、安全に扱える整数の最大値は $2^{53} - 1$ (9,007,199,254,740,991)までに制限されています 。これを背景に、最新のECMAScript(ES2024)では JSON.parse() に画期的な機能拡張が行われました。
context.source による正確なパース
従来の JSON.parse() では、解析の途中で数値が自動的に Number 型に変換されてしまうため、reviver 関数が呼ばれる頃には既に精度が失われていました 。
最新仕様では、reviver 関数の第3引数として context オブジェクトが渡されるようになりました 。この context.source を参照することで、変換前の「生のJSONテキスト」をそのまま取得でき、それを BigInt などに安全に変換することが可能となります 。
javascript
const bigNumJson = '{"orderId": 900719925474099912345}';
const result = JSON.parse(bigNumJson, (key, value, context) => {
if (key === "orderId") {
// context.source は "900719925474099912345" という生の文字列を保持している
return BigInt(context.source);
}
return value;
});
console.log(result.orderId); // 900719925474099912345n (精度が保たれている)この機能は、2025年現在、主要なブラウザ(Chrome 114+, Firefox 135+, Edge 114+)で既に広く利用可能となっており、基盤としての安定性が向上しています 。


循環参照の検知と回避策
JavaScriptにおいて、オブジェクトが自分自身を直接、あるいは他のオブジェクトを介して間接的に参照している状態を「循環参照」と呼びます 。JSONは本質的に木構造(一方通行の階層構造)を想定したデータ形式であるため、循環参照を含むオブジェクトを JSON.stringify() しようとすると、無限ループを防止するためにエラーが発生します 。
循環参照によるエラーの例
javascript
const node = { name: "Root" };
node.self = node; // 循環参照を作成
JSON.stringify(node); // TypeError: cyclic object value (ブラウザによりメッセージは異なる)解決策:WeakSetを用いたフィルタリング
循環参照を安全に処理するには、変換過程で「既に処理したオブジェクトかどうか」を記録しておく必要があります。これには、メモリ管理に優れた WeakSet を活用するのがベストプラクティスです 。
javascript
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value!== null) {
if (seen.has(value)) {
return; // すでに見たオブジェクトなら、その項目を削除(undefinedを返す)
}
seen.add(value);
}
return value;
};
};
const safeJson = JSON.stringify(node, getCircularReplacer());
console.log(safeJson); // '{"name":"Root"}' (循環部分は除外される)このように replacer を自作することで、複雑なデータ構造もエラーを出さずに保存可能な形式に変換できます 。
JSON.rawJSON() と数値のロスレス・シリアライズ
BigInt 値を JSON.stringify() で変換しようとすると、通常は TypeError が発生します 。また、数値を文字列としてシリアライズすると、受信側で「数値」として認識されず、処理が煩雑になることがあります。
これを解決するのが、ES2025で導入された JSON.rawJSON() です 。このメソッドは、引数に渡した文字列を「そのままのJSONの一部」としてマークする特別なオブジェクトを作成します 。これにより、JavaScriptの数値型の限界に縛られず、任意の精度を持つ「数値」をJSONに直接埋め込むことができます 。
javascript
const price = 12345678901234567890n;
const payload = JSON.stringify({
id: 1,
amount: JSON.rawJSON(price.toString())
});
console.log(payload); // '{"id":1,"amount":12345678901234567890}'amount の値に引用符が付いていない点に注目してください。これにより、PythonやJavaなど、JavaScriptよりも高い数値精度を持つ他言語のシステムへ、データを損なうことなく受け渡すことが可能になります 。
ウェブ開発の現場で使われるJSONの実践例
JSONは単独で使われるだけでなく、Web APIやブラウザの保存機能と組み合わせて威力を発揮します。
Fetch API によるデータの送受信
現代のウェブアプリでは、サーバーからデータを取得する際、ほとんどのケースで Fetch API が利用されます。Response.json() メソッドを使うと、HTTPレスポンスのボディを自動的にパースしてオブジェクトとして取得できます 。
javascript
async function getUserData() {
const response = await fetch("https://api.example.com/user/1");
const user = await response.json(); // ここで内部的に JSON.parse が実行される
console.log(user.name);
}逆にデータを送信する場合は、headers で Content-Type: application/json を指定し、body に JSON.stringify() した文字列を渡します 。
Web Storage (localStorage) への保存
ブラウザにデータを永続化する localStorage は、文字列しか保存できない仕様になっています 。そのため、複雑な設定値やユーザー情報を保存するにはJSON変換が必須です 。
javascript
const themeSettings = { dark: true, opacity: 0.8 };
// 保存時:オブジェクトをJSON文字列に変換
localStorage.setItem("settings", JSON.stringify(themeSettings));
// 取得時:文字列を読み出し、オブジェクトへ復元
const saved = localStorage.getItem("settings");
if (saved) {
const settings = JSON.parse(saved);
console.log(settings.dark);
}ただし、localStorage への読み書きは「同期処理」であり、処理中はブラウザのメインスレッドをブロックします 。極端に巨大なデータを頻繁にパース・文字列化すると、画面の動きがカクつく(Jank)原因となるため、データ量には注意が必要です 。


JSONモジュールのネイティブサポート (Baseline 2025)
これまでJavaScriptファイルからJSONデータを読み込むには、前述の fetch を使うか、Webpackなどのビルドツールを使うのが一般的でした。しかし現在では、「JSONモジュール」というブラウザの標準機能によって、あたかもJavaScriptファイルであるかのようにJSONをインポートできるようになりました 。
import 属性と with 構文
JSONをインポートする際は、セキュリティ上の理由から with { type: "json" } という記述を添える必要があります 。これは、サーバーが偽装されたJavaScriptファイルを送り込み、開発者の意図しないコードが実行されるのを防ぐためのガードレール(型アサーション)として機能します 。
javascript
// index.js (type="module" である必要があります)
import data from "./config.json" with { type: "json" };
console.log(data.version);この機能は、2025年4月に「Baseline 2025」として全主要ブラウザ(Chrome, Firefox, Safari, Edge)で利用可能となりました 。これにより、開発環境のセットアップなしに、ネイティブなESモジュール環境でJSONファイルを扱うことが非常に容易になっています 。


セキュリティとパフォーマンスの考慮事項
JSONを扱う際、開発者が意識すべき「安全性」と「速度」についても触れておきます。
安全なパース: eval() を使ってJSONを解析してはいけません。JSON.parse() は厳格な文法チェックを行うため安全ですが、eval() は任意のコードを実行できてしまい、XSS攻撃の脆弱性となります 。
パフォーマンスのオーバーヘッド: JSON.stringify や JSON.parse は非常に高速ですが、データサイズが数メガバイトを超えると、パフォーマンスに影響を与え始めます 。特に頻繁な更新が発生するリアルタイム通信では、変換コストが累積することを考慮すべきです 。
シリアライズによる情報欠落: 前述の通り、関数や undefined はシリアライズで失われます。また、Set や Map といった新しいデータ構造も、そのままでは空のオブジェクト {} に変換されてしまいます 。これらを保存したい場合は、toJSON メソッドを実装するか、replacer で配列形式などに変換する工夫が必要です 。
まとめ
JSONは、JavaScriptを学ぶ上で避けては通れない、そして一度習得すればあらゆる場面で役立つ強力なスキルです。基礎となる JSON.parse() と JSON.stringify() の使い方をマスターしたら、次は最新仕様である context.source による数値精度の維持や、JSONモジュールによるネイティブなインポートにも挑戦してみてください。技術の進化によって、JavaScriptとJSONの境界線はよりシームレスになりつつあります。本稿で紹介した最新のテクニックを活用することで、より安全で、精度の高いデータのやり取りを実現できるはずです。
参考資料
1. MDN: JSON.stringify()、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
2. MDN: Response.json()、https://developer.mozilla.org/en-US/docs/Web/API/Response/json
3. MDN: JSON (Standard built-in objects)、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
4. MDN: Working with JSON、https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/JSON
5. MDN: JSON.parse()、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
6. StackOverflow: Stringify BigInt as a number instead of string、https://stackoverflow.com/questions/77829479/stringify-bigint-as-a-number-instead-of-string
7. MDN: BigInt not serializable in JSON、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/BigInt_not_serializable
8. MDN: BigInt、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
9. Blog: JavaScript BigInt and JSON、https://blog.rasc.ch/2019/01/js-bigint-json.html
10. Tencent Cloud: JSON circular reference error handling best practices、https://www.tencentcloud.com/techpedia/127975
11. freeCodeCamp: Circular Reference in JavaScript Explained、https://www.freecodecamp.org/news/circular-reference-in-javascript-explained/
12. GeeksforGeeks: Why Circular Reference is BAD in JavaScript?、https://www.geeksforgeeks.org/javascript/why-circular-reference-is-bad-in-javascript/
13. MDN: TypeError: cyclic object value、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
14. StackOverflow: Detecting and fixing circular references in JavaScript、https://stackoverflow.com/questions/14962018/detecting-and-fixing-circular-references-in-javascript
15. MDN: Using the Web Storage API、https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
16. HackMD: Fetch API and Local Storage、https://hackmd.io/@yveshema/fetch-api-and-local-storage
17. RxDB: Understanding the Limitations of localstorage、https://rxdb.info/articles/localstorage.html
18. MDN: Window.localStorage、https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
19. StackOverflow: How to store and retrieve JSON data into local storage、https://stackoverflow.com/questions/34493531/how-to-store-and-retrieve-json-data-into-local-storage
20. MDN: import attributes (with syntax)、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/with
21. web.dev: JSON module scripts and import attributes、https://web.dev/blog/json-imports-baseline-newly-available
22. TypeScript Handbook: Modules、https://www.typescriptlang.org/docs/handbook/modules/theory.html
23. Node.js Documentation: ECMAScript modules、https://nodejs.org/api/esm.html
24. MDN: import、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
25. TC39 Proposal: JSON.parseImmutable、https://tc39.es/proposal-json-parseimmutable/
26. TC39 Proposal: JSON.parse with source、https://tc39.es/proposal-json-parse-with-source
27. GitHub: tc39/proposal-json-parse-with-source、https://github.com/tc39/proposal-json-parse-with-source
28. Chromium Blog: Intent to Ship: JSON.parse source text access、https://groups.google.com/a/chromium.org/g/blink-dev/c/K_gwfyX8yg8
29. GitHub Issues: tc39/proposal-json-parse-with-source/issues/39、https://github.com/tc39/proposal-json-parse-with-source/issues/39
30. MDN: JSON.stringify() Demo & Syntax、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
31. StackOverflow: How to stringify objects through JSON's replacer function、https://stackoverflow.com/questions/30280322/how-to-stringify-objects-through-jsons-replacer-function
32. Gist: JSON.replacer.js、https://gist.github.com/0265db39aac4ec689771b756215efabe
33. ESDiscuss: String.prototype.replace problems with JSON.stringify、https://esdiscuss.org/topic/string-prototype-replace-problems-with-json-stringify-and-serialization-of-objects
34. Blog: Customizing JSON.parse and JSON.stringify、https://joeattardi.dev/customizing-jsonparse-and-jsonstringify
35. MDN: JSON.parse() Parameters & Examples、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
36. GitHub: JSON.parse source text access README、https://github.com/tc39/proposal-json-parse-with-source
37. Reddit: JSON.parse reviver function discussion、https://www.reddit.com/r/learnjavascript/comments/6zytuc/jsonparse_reviver_function/
38. 2ality: JSON.parse() with source、https://2ality.com/2022/11/json-parse-with-source.html
39. StackOverflow: JSON.parse() reviver function higher level access、https://stackoverflow.com/questions/72268580/json-parse-reviver-function-how-to-access-to-a-higher-level-object
40. MDN: Import attributes (ES2025)、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/with
41. Exploring JS: New in ECMAScript 2025、https://exploringjs.com/js/book/ch_new-javascript-features.html
42. CodeGuage: What Exactly Are Import Attributes in JavaScript?、https://www.codeguage.com/blog/import-attributes-js
43. Can I Use: Import attributes (with syntax)、https://caniuse.com/?search=import%20attributes
44. MDN: JSON.parse() Browser compatibility、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
45. MDN: JSON Static Methods、https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
46. Can I Use: JSON.parse source text access、https://caniuse.com/#search=JSON.parse
47. MDN Glossary: JSON type representation、https://developer.mozilla.org/en-US/docs/Glossary/JSON_type_representation




コメント