JSONのDeep Mergeとは — 設定ファイルの合成パターン
Deep Mergeはオブジェクトをネストの深いところまで再帰的にマージする操作です。設定ファイルのデフォルト値への上書き、複数ソースからのデータ統合、APIレスポンスの合成など、多くの場面で必要になります。
Shallow MergeとDeep Mergeの違い
Object.assign()やスプレッド構文({...a, ...b})はShallow Mergeで、ネストしたオブジェクトは参照ごと上書きされます。つまりaが{x:{a:1,b:2}}、bが{x:{c:3}}のとき、{...a,...b}は{x:{c:3}}となりa.x.a, a.x.bが消えます。Deep Mergeはネストオブジェクトを再帰的にマージするため{x:{a:1,b:2,c:3}}になります。
配列のマージ戦略
配列の扱いはユースケースによって変わります。「上書き」戦略は後のスロットの配列で前のスロットの配列を完全に置き換えます(設定の上書きに適切)。「連結」戦略は配列を末尾に結合します(タグ・ロールの追加に適切)。どちらが正しいかはアプリケーションのドメイン要件によるため、選択できるようにしておくことが重要です。
設定ファイルの階層マージパターン
Node.jsアプリでよく使われるパターンとして、default.json → {NODE_ENV}.json → local.json の順にDeep Mergeすることで環境別設定を実現します。左側(優先度低)から右側(優先度高)の順でマージし、後のファイルの値が優先されます。このツールも同じ「後スロット優先」のマージ順を採用しています。
循環参照と特殊ケースへの対処
一般的なDeep Merge実装で気をつけるべき点として、null値の扱い(nullで上書きするか無視するか)、配列内のオブジェクトのマージ方法、Dateやエラーなど特殊なオブジェクトの扱い、循環参照の検出があります。このツールでは純粋なJSONのみを対象とするため循環参照は発生せず、nullは上書きとして扱います。