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

JavaScriptでネストされたJSONオブジェクトを再帰的に検索する方法

```html

まず、次のような入れ子構造(ネスト)を持つJSONオブジェクトを用意します。オブジェクトの中にさらにオブジェクトや配列が含まれ、目的のデータがどこにあるのか一目では分からない——こうしたケースは実際の開発でもよく遭遇します。

const obj = {
    id: 1,
    title: 'hello world',
    child: {
        id: null,
        title: 'foobar',
        child: {
            id: null,
            title: 'i should be in results array '
        }
    },
    foo: {
        id: null,
        title: 'i should be in results array too!'
    },
    deep: [
        {
            id: null,
            value: 'yo'
        }, {
            id: null,
            value: 'yo2'
        }
    ]
};

実現したいこと

今回作成するのは、次の3つの引数を受け取るJavaScript関数です。

  • 第1引数:検索対象のオブジェクト
  • 第2引数:キー名の文字列
  • 第3引数:値の文字列

この関数はJSONオブジェクト全体を走査し、指定されたキーと値の組み合わせを持つすべてのオブジェクトを見つけ出します。そして、該当するオブジェクトをまとめた配列を返します。

解決のためのアプローチ

階層の深さが事前には分からないため、ここでは再帰処理を活用します。具体的な手順は以下のとおりです。

  • 検索対象の値がfalsy(false、null、undefinedなど)であるか、オブジェクト型でない場合は、その時点で処理を打ち切って戻る
  • 現在注目しているオブジェクトで、指定されたキーと値が一致していれば、そのオブジェクト自体を結果セットに追加する
  • Object.keys()でキーの一覧を取得し、各プロパティの値に対して同じ検索関数を再帰的に呼び出す

最後に、収集したオブジェクトを格納した配列を呼び出し元へ返せば完成です。

コード例

const findObject = (obj = {}, key, value) => {
    const result = [];
    const recursiveSearch = (obj = {}) => {
        if (!obj || typeof obj !== 'object') {
            return;
        }
        if (obj[key] === value) {
            result.push(obj);
        }
        Object.keys(obj).forEach(function (k) {
            recursiveSearch(obj[k]);
        });
    };
    recursiveSearch(obj);
    return result;
};
console.log(findObject(obj, 'id', null));

コードのポイント

処理の中心となるのは内部関数recursiveSearchです。typeofによる型チェックで文字列や数値といった末端の値を除外しながら、オブジェクトや配列だけを再帰的に掘り下げていきます。条件に合致したオブジェクトは、参照ごとそのまま結果配列に追加されるため、見つかったオブジェクトの全体構造を後からそのまま利用できるのが大きな特徴です。

出力結果

[
    {
        id: null,
        title: 'foobar',
        child: {
            id: null,
            title: 'i should be in results array '
        }
    },
    {
        id: null,
        title: 'i should be in results array '
    },
    {
        id: null,
        title: 'i should be in results array too!'
    },
    {
        id: null,
        value: 'yo'
    },
    {
        id: null,
        value: 'yo2'
    }
]

このようにfindObject(obj, 'id', null)を実行すると、ネストの深い位置にあるオブジェクトも漏らすことなく、idnullであるすべてのオブジェクトを配列として取得できました。

  1. JavaScriptにおけるオブジェクトの分割代入(Destructuring)の使い方

    JavaScriptでは、分割代入(Destructuring)と呼ばれる構文を使うことで、オブジェクトから特定のプロパティを簡単に取り出し、個別の変数に代入することができます。従来の方法では、obj.firstName のようにプロパティへ一つずつアクセスする必要がありましたが、分割代入を使えば1行で簡潔に記述できます。オブジェクトの分割代入の基本構文基本的な書き方は以下の通りです。let { プロパティ名1, プロパティ名2, プロパティ名3 } = オブジェクト;波括弧 {} の中に取り出したいプロパティ名を列挙するだけで、同名の変数にそれぞれの値が代入されます。実装例以下は、オブジェク

  2. JavaScriptのWeakMapオブジェクトとは?基本の使い方をサンプルコード付きで解説

    WeakMapは、キーと値のペアを要素として持つオブジェクトです。通常のMapとの大きな違いは、キーに必ずオブジェクトを指定しなければならないという点です。値にはプリミティブ型(文字列や数値など)でもオブジェクトでも何でも格納できます。 さらに重要な特徴として、WeakMapのキーとして使用されたオブジェクトへの参照が他に存在しなくなると、そのオブジェクトはガベージコレクション(GC)によって自動的にメモリから解放されます。これにより、メモリリークを防ぎながら一時的なデータを安全に関連付けることができます。 WeakMapの主な特徴 キーにはオブジェクトのみ指定可能(プリミティブ値はキーにで