JSONとCSVにおけるデータ構造の差異とフラット化の必要性
JSON(JavaScript Object Notation)は,オブジェクトや配列を何層にも入れ子にして表現できる階層型のデータフォーマットです.ひとつのキーに対してさらに複数のキーと値のペアを格納できるため,複雑な関係性を持つデータを直感的に表現できるという利点があります.
たとえば,ユーザー情報の中にプロフィールオブジェクトがあり,その中にさらに住所オブジェクトが格納されているといった具合に,現実世界の複雑な構造をそのまま反映させることが可能です.対照的にCSV(Comma-Separated Values)は,行と列からなる二次元の表形式データです.
各行が1つのレコードに対応し,各列が1つの属性を示すという制約があります.リレーショナルデータベースのテーブルや表計算ソフトのシートのように,フラットで均質な構造を持つため,集計や一覧表示に非常に適しています.
この構造的な根本の違いから,JSONをそのままCSVに当てはめることは構造上できません.階層構造を持つJSONをCSVの平坦な表形式に変換するためには,多重にネストされたデータを1次元の列名として展開する「フラット化」と呼ばれる処理が不可欠となります.フラット化では,再帰的な探索のような手法を用いてJSONのプロパティを巡回し,親ノードと子ノードのプロパティ名を指定された区切り文字で結合して単一の文字列キーを生成し続けます.
このプロセスにより,どれほど深い階層を持つオブジェクトであっても,表計算ソフトで扱いやすい平坦な列識別子として再構成されることになります.ただし,この変換プロセスは多次元の情報を強制的に二次元へと下げる操作であるため,表現力の違いによる情報の欠落や,再構築時の解釈の揺らぎといった課題を常に内包しています.
本実装のフラット化変換ツールを利用する際は,これら二つのフォーマットが持つ根本的な構造の違いと,次元を落とすことによる影響を十分に理解した上で,データの扱い方を検討することが求められます.
階層キーの連結と配列添字による列名の生成規則
JSON内のネストされたオブジェクトを平坦化する際,本ツールでは指定された区切り文字(デフォルトではドット)を用いて親キーと子キーを連結するという規則を採用しています.たとえば,userという親キーの下にnameという子キーがある場合,これらは連結されて「user.name」という1つのヘッダー名として展開されます.
さらに深い階層があれば,「user.profile.address.city」のように順次連結されていきます.なお,階層や値の衝突を防ぐため,区切り文字を含むキーや空のキーは拒否されます.
配列が含まれる場合の処理もデータ構造を維持する上で非常に重要です.JSONの配列は複数の要素を順序付けて保持しますが,CSVには配列という概念そのものが存在しません.そのため,配列の要素ごとに個別の列を割り当てる必要が生じます.本実装では,配列のインデックス(添字)をキー名の一部として活用し,「items.0」や「items.1」といった形で要素の位置を示す数値を列名に組み込みます(添字の上限は10000).
これにより,多次元のリストデータであっても,インデックスに基づく一意のヘッダー名として表形式の列に展開して配置されます.また,CSV生成時にはヘッダーのエスケープが行われ,全レコードにわたる列名のunionから重複が正常に除去されます(重複ヘッダーが拒否されるのはCSV入力時のみです).
この規則によって生成されるヘッダー集合は,同一階層における同名プロパティの競合を回避し,データが元々どの位置にあったのかという構造的な情報を保持する役割を担います.ただし,深さ64,配列添字10000,入力各200万codeunit,1万行,20万セルといった上限が設けられており,極端に巨大なデータや深いネストは安全に制限されます.
階層キーの連結と配列添字の展開は,元のデータ構造を文字列として表現するための効果的な工夫ですが,構造の複雑さに応じた変換制約がある点に留意して利用してください.
JSONからCSVへの変換と値のテキスト化プロセス
JSONオブジェクトをCSVに変換する過程では,抽出されたキー群をヘッダー行として並べ,各レコードの対応するプロパティ値をテキスト化して出力する処理が順番に行われます.JSON内には文字列,数値,真偽値,nullといった多様なデータ型が明確に定義されていますが,CSVというフォーマットは基本的にすべての値をプレーンテキストの文字列として扱う性質があります.
本ツールの実装では,各プロパティの値を文字列に変換し,カンマやタブなどの区切り文字で区切られた列として配置します.値の中に区切り文字,改行,ダブルクォートなどの特殊な文字が含まれている場合は,データの境界が崩れるのを防ぐためにフィールド全体をダブルクォートで囲むエスケープ処理が行われ,ヘッダーも適切にエスケープされます.
このテキスト化のプロセスにおいて,元のデータが持ついくつかの型の特性は失われるか,あるいは別の形で表現されることになります.nullや未定義のプロパティは空のフィールドとして出力され,空のオブジェクトや空の配列も固有の文字列表現に置き換わります.そのため,CSVとして出力された結果は見た目上データが整然と並んでいるように見えても,プログラミング言語が解釈できる明確なデータ型としての情報は保持されていません.
JSONからCSVへの一方向の変換においては,データを表として人間が閲覧したり,表計算ソフトで集計したりする目的に適していますが,型の厳密性が失われるテキスト化プロセスであることを前提として活用していただく必要があります.
CSVからJSONへの逆変換における型推定の仕組み
CSV形式からJSON形式への逆変換(アンフラット化と呼ばれる処理)では,ドット等で区切られたヘッダー名を解析し,元の階層構造を再構築する処理が行われます.ヘッダー名に「items.0.id」のような数値が含まれている場合は,それを配列のインデックスとして解釈し,オブジェクトの代わりに配列を生成してデータを適切な位置に格納します.
この過程で直面する最大の課題が,CSVから読み込まれるすべての値が文字列として扱われるという点です.JSONの構造に戻す際,すべてを文字列のままにしておくと,システム間でデータを連携する際などに本来のデータとして不適切な状態となるため,本実装では簡易的な型推定のロジックを試みます.
具体的には,文字列が「true」や「false」であれば真偽値に変換し,数値として解釈可能な文字列であれば数値型へのパースを行います.
しかし,この型推定はあくまで文字列のパターンに基づくヒューリスティックな判定を行っているに過ぎません.したがって,データの文脈や意図に応じた高度な型推論を行うわけではありません.たとえば,商品コード,電話番号,あるいは識別子として意図された数値文字列であっても,変換エンジンが単なる数値として解釈可能と判断すれば,文字列ではなく数値型に変換されます.
CSVからJSONへ戻す機能は,元の構造をある程度復元する手段としては非常に有用ですが,この型推定の仕組みによって元のデータ型とは異なる解釈がなされる可能性を常に考慮して運用する必要があります.
相互変換の限界と元の状態への往復処理ができない具体例
本ツールはJSONとCSVの双方向変換機能を提供していますが,フォーマットの根本的な特性や実装上の制約により,変換前の状態に戻らない非可逆なケースが複数存在します.本ツールを利用する上で,これらの限界を把握しておくことは非常に重要です.なお,付属のサンプルCSVはJSONサンプルから整合して生成されています.
第一の具体例として,ゼロ埋めされた数値の扱いが挙げられます.元のJSONで「001」という文字列型の値として定義されていた場合,CSVに出力された時点では文字として書き出されます.しかし,これを再びJSONに戻す際,CSVのテキストを読み取った変換処理が型推定を行い,数値の1に変換してしまい,元のゼロ埋めされた文字列表現が失われます.
第二に,空文字やnullの表現です.JSONにおける空文字やnullは,CSVに変換されるとどちらも中身のない空のセルとして表現されます.逆変換する際,空のセルは一律にnullと判定されるため,元が空文字だったのかnullだったのかを区別して復元することはできません.
第三に,元のJSONのキー名そのものに区切り文字(ドットなど)が含まれている場合や空キー,階層・値・型の衝突です.本実装ではこれらを未然に防ぐためエラーとして拒否します.
さらに,真偽値のtrueという文字列も型推定によって真偽値型に変換されるため,文字列としての値と真偽値としての値の区別が消失します.スペースは保持されますが,既存の型推論が適用されるため完全な可逆性は担保されない点にご注意ください.
表計算ソフトでの利用,大容量データ,および機密情報の注意点
フラット化されたCSVデータは,Excelなどの一般的な表計算ソフトで読み込むことで,データのフィルタリング,並べ替え,集計が容易に行えるようになります.ただし,表計算ソフト自体にもデータを取り込む際の独自の型推論機能が備わっているため,CSV内にエスケープされた値や長い数値文字列が存在する場合,指数表記に変換されたり,意図しない日付形式で表示されたりすることがあります.
また,式文字列の自動無害化は行われないため,表計算ソフト側での数式実行にはご注意ください.
処理するデータの容量については,深さ64,配列添字10000,各入力200万codeunit,1万行,20万セルといった上限が設定されています.さらに,CSV逆変換時には累積上限として,sparse配列のnull補完を含む展開node合計20万まで,および整形JSON出力の推計500万文字までという制限が設けられており,これはCSVセル数の上限とは別に管理されます.
また,CSVダウンロード時に生成されたURLは使用後に解放されます.大容量のデータを変換する場合は,これらの上限値に留意してご利用ください.
セキュリティおよび機密情報の取り扱いに関して,本実装ではnull-prototypeやown-propertyチェックにより__proto__,prototype,constructorといった安全でないキーを拒否し,厳格なCSVパース(引用符,列幅,BOM,改行,重複ヘッダー拒否)を実施しています.
入力データに対する処理はローカルのJavaScript環境で完結し,外部ネットワークへデータの実体を送信することはありません.ただし,個人情報や重要な財務情報を扱う場合は組織のセキュリティ規定に従ってください.また,会計,税務,法的な証明に関わる処理に変換データを利用する際は,型推論による情報の変質がないかを十分に確認し,必要な場合は各分野の専門家にご相談ください.