JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptでネストされたオブジェクトを再帰的にフラット化する方法

JavaScriptでは、入れ子になった(ネストされた)オブジェクトを、ドット区切りのキーを持つフラットなオブジェクトへ変換したい場面があります。本記事では、再帰処理を使ってこの変換を実現する関数の作り方を解説します。

やりたいこと

たとえば、次のような入力オブジェクトがあったとします。

const input = {
    a: 0,
    b: {x: {y: 1, z: 2}},
    c: 3
};

このオブジェクトに対して関数を実行すると、出力は次のようになることが期待されます。

const output = {
    a: 0,
    'b.x.y': 1,
    'b.x.z': 2,
    c: 3
}

つまり、ネストされたプロパティのパスを「b.x.y」のようにドットで連結した文字列をキーとして、すべての値を一段階の深さに展開するわけです。

実装のアプローチ

この問題は再帰(recursion)を使うことでシンプルに解決できます。オブジェクトの各キーを順番に調べ、値がオブジェクトであれば再帰的に処理を続け、そうでなければ現在のパスをキーとして結果に格納します。

コード例

const obj = {
    a: 1,
    b: {x: {y: 1, z: 2}},
    c: 3
};
const obj1 = {
    a: 0,
    b: 0,
    c: 0
};
const object = { a: 0, b: { x: { y: 1, z: 2 } }, c: 3 };
const stringifyKeys = (obj, str = '', fresh = {}) => {
    const keys = Object.keys(obj);
    for(let i = 0; i < keys.length; i++){
        if(typeof obj[keys[i]] === "object" && !Array.isArray(obj[keys[i]])
        && obj[keys[i]]){
            stringifyKeys(obj[keys[i]], str+`${keys[i]}.`, fresh);
        }else{
            fresh[str+keys[i]] = obj[keys[i]];
        };
    }
    return fresh;
};
console.log(stringifyKeys(obj));
console.log(stringifyKeys(object));
console.log(stringifyKeys(obj1));

コードのポイント

  • 引数のデフォルト値:第2引数 str はこれまで辿ってきたキーのパス、第3引数 fresh は結果を格納するオブジェクトです。どちらもデフォルト値を持たせているため、最初の呼び出しでは引数を省略できます。
  • オブジェクト判定の条件typeof === "object" に加えて Array.isArray() で配列を除外し、さらに null チェックを行っています。JavaScriptでは nulltypeof の結果が "object" になるため、このチェックは重要です。
  • パスの蓄積:ネストしたオブジェクトを見つけるたびに、現在のキーとドットを結合してパスを組み立て、次の再帰呼び出しに渡します。

実行結果

コンソールには以下のように出力されます。

{ a: 1, 'b.x.y': 1, 'b.x.z': 2, c: 3 }
{ a: 0, 'b.x.y': 1, 'b.x.z': 2, c: 3 }
{ a: 0, b: 0, c: 0 }

ネストされたオブジェクトは正しくフラット化され、もともとネストされていないオブジェクト(obj1)はそのままの形で返されていることがわかります。この関数は、設定データの正規化やAPIレスポンスの加工など、さまざまな場面で活用できる汎用的なユーティリティです。

  1. JavaScriptのRegExp(正規表現)オブジェクトとは?基本の使い方をわかりやすく解説

    RegExp(正規表現)オブジェクトは、テキストに対してパターンマッチングを行い、目的の文字列部分を検索・抽出するために使用されます。JavaScriptでは、RegExpオブジェクトを「RegExpコンストラクタ」または「リテラル構文」の2通りの方法で作成できます。 RegExpオブジェクトの作成方法 コンストラクタを使用する場合: new RegExp(pattern) リテラル構文を使用する場合: /pattern/ 主なメソッド test():文字列がパターンに一致するかどうかを真偽値(true / false)で返します。 exec():パターンに一致した文字列を返します。

  2. JavaScriptのオブジェクト初期化子とは?使い方をサンプルコードで解説

    オブジェクト初期化子とは オブジェクト初期化子(Object Initializer)は、新しく生成したオブジェクトを初期化するための式です。波括弧 {} の中に、「プロパティ名」と「それに対応する値」のペアを0個以上、カンマ区切りで列挙して記述します。 これにより、変数宣言と同時にオブジェクトの中身を簡単に定義することができます。 以下は、JavaScriptでオブジェクト初期化子を使用したサンプルコードです。 サンプルコード <!DOCTYPE html> <html lang="en"> <head> <meta chars