2016-03-24 10 views
1

ツリービューにバインドするために使用する大きなネストJSONファイルがあります。このツリービューのデータソースをテキストで検索し、その親まで一致するすべてのノードを取得して、ツリー構造を保持できるようにします。だから私は以下のようなJSONを持って言うことができます:jQueryまたはJavascriptを使用してネストされたJSONを検索する

テキストボックスに今

[ 
 
    { 
 
    "x": "Root-1", 
 
    "y": "000001", 
 
    "c": [ 
 
     { 
 
     "x": "child-1", 
 
     "y": "000001.1" 
 
     }, 
 
     { 
 
     "x": "child-2", 
 
     "y": "000001.2", 
 
     "c": [ 
 
      { 
 
      "x": "child-3", 
 
      "y": "000001.3" 
 
      } 
 
     ] 
 
     } 
 
    ] 
 
    }, 
 
    { 
 
    "x": "Root-2", 
 
    "y": "000002", 
 
    "c": [ 
 
     { 
 
     "x": "child-4", 
 
     "y": "000002.1" 
 
     }, 
 
     { 
 
     "x": "child-5", 
 
     "y": "000002.2", 
 
     "c": [ 
 
      { 
 
      "x": "child-6", 
 
      "y": "000002.3", 
 
      "c": [ 
 
       { 
 
       "x": "child-7", 
 
       "y": "000002.4" 
 
       } 
 
      ] 
 
      } 
 
     ] 
 
     } 
 
    ] 
 
    } 
 
]

、私はのために含まれている検索やりたい:「1.3」と、それは同じネスティングを持つオブジェクトの下に私を返す必要があります:

子-3(これは一致しています)、子2(子3の親)、ルート1(子2の親)です。

今、このJSONをツリービューにバインドすることができます。

+0

古いと悪い質問:何を試してみましたか、私たちにいくつかのコードを教えてください – madalinivascu

+0

希望の戻り値の例を追加してください。 –

+0

簡単な方法:繰り返しながら各配列要素をJSON.stringifyし、用語をJSONにマッチさせます。 'r.filter(x => JSON.stringify(x).match(term))' – dandavis

答えて

0

この提案は、可能な配列を反復処理し、その前のノードを持つすべてのレベルの配列を構築し、searchが見つかるとパスが結果にプッシュされます。繰り返しは短絡で動作します。次のレベルでは、関数は新しい基底と実際のノードへの前のパスで再び呼び出されます。

function getNodes(tree, search) { 
 
    function n(a, t) { 
 
     return Array.isArray(a) && a.some(function (b) { 
 
      return b.y.match(search) && r.push([].concat(b, t)) || n(b.c, [].concat(b, t)); 
 
     }); 
 
    } 
 

 
    var r = []; 
 
    n(tree, []); 
 
    return r; 
 
} 
 

 
var tree = [{ "x": "Root-1", "y": "000001", "c": [{ "x": "child-1", "y": "000001.1" }, { "x": "child-2", "y": "000001.2", "c": [{ "x": "child-3", "y": "000001.3" }] }] }, { "x": "Root-2", "y": "000002", "c": [{ "x": "child-4", "y": "000002.1" }, { "x": "child-5", "y": "000002.2", "c": [{ "x": "child-6", "y": "000002.3", "c": [{ "x": "child-7", "y": "000002.4" }] }] }] }]; 
 

 
document.write('<pre>' + JSON.stringify(getNodes(tree, '1.3'), 0, 4) + '</pre>');

0

あなたはこれらの再帰関数を使用することができます。

var result = find(data, 1, 1, 0, 0); 

function find() { 
    var args = [].slice.call(arguments); 
    var root = args.shift(); 
    if(args.length == 0) return []; 
    var index = args.shift(); 
    root = nthChild(root, index); 
    if(typeof root === 'undefined') { 
     throw Error("Invalid index " + index + " at level " + args.length + " from the tail!"); 
    } 
    args.unshift(root); 
    return [root].concat(find.apply(undefined, args)); 
} 


function nthChild(root, index) { 
    // If we are not in an array, let take the "c" attribute. 
    if(!Array.isArray(root)) root = root.c; 
    return root[index]; 
} 
1

実は一度文字列化任意のテキスト文字列とは異なり、JSONデータは、したがって、かなり定期的に構造化文字列を生成し、私たちは涼しい適用される場合がありますコードを2〜3のライナーに減らす正規表現。この1つまたは再帰的または反復的な方が効率的かどうかはわかりません。後で試してみるよ。

TL & DRコードはこれです。 F12はあなたの友人です。

function regExpEscape(literal_string) { 
    return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&'); 
} 
// assuming that your json data is assigned to a variable jd 
var js = JSON.stringify(jd), 
    sd = 1.3.toString(), //this input value should be supplied as string 
    rx1 = new RegExp('{"x":"([\\w-]+)[",:\\w]+(?=' + regExpEscape(sd) + ')',"g"), 
    rar = [], 
result = []; 

rar = rx1.exec(js); // < ["{"x":"child-3","y":"00000", "child-3"] 
rar.length && result.push(rar[1]); // if rar is not empty save rar[1] to result 
var rx2 = new RegExp('{"x":"([\\w-]+)(?=[":,\\.\\w-]+\\[{[\\[{}":,\\.\\w-]+' + regExpEscape(result[0]) + ')',"g"); 
while (!!(rar = rx2.exec(js))){result.push(rar[1])} // ["child-3", "Root-1", "child-2"] 

一部を伝える物語:

をわずか2つのステップで、我々は後にある結果を得ることができます。

1.3が存在するかどうかをチェックしてxプロパティの値(name)を得るには、/{"x":"([\w-]+)[",:\w]+(?=1\.3)/g regexpを使用できます。しかし、この正規表現を再利用可能にする方法を見つけよう。

// assuming that your search data is assigned to a variable sd 
function regExpEscape(literal_string) { 
    return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&'); 
} 
var rx = '/{"x":"([\w-]+)[",:\w]+(?=' + regExpEscape(sd) + ')/g'); 

ここで、任意の検索データに対して正規表現を使用できます。私たちが残した場所から続けましょう...

// assuming that your json data is assigned to a variable jd 
var js = JSON.stringify(jd), 
    sd = 1.3.toString(), //this input value should be supplied as string 
    rx1 = new RegExp('{"x":"([\\w-]+)[",:\\w]+(?=' + regExpEscape(sd) + ')',"g"), 
    rar = [], 
result = []; 

rar = rx1.exec(js); // < ["{"x":"child-3","y":"00000", "child-3"] 
rar.length && result.push(rar[1]); // if rar is not empty save rar[1] to result 

これまでのところとても良いです。私たちは、私たちが探していた結果を持つオブジェクトの名前を持っています。今の両親から同じ情報を取得するために、我々は、子の間にこれら二つの事実

  1. を使用し、それがどの]の文字があってはならない親です。
  2. [文字に達した場合、親要素に到達します。

クールで持ち運びができます。私はこれの上に頭脳の少しが溶けて来て、それを考え出しました/{"x":"([\w-]+)(?=[":,\.\w-]+\[{[\[{}":,\.\w-]+child-3)/gまあまあそれはややわかりにくいですが、実際はかなりシンプルです。私を通過させてください。これは、xxx(yyy)の前に(?= [許可された文字]、それに続いて[いくつかの許可された文字]、その後に "子-3")続けなければなりません。子どもは誰でも、両親と兄弟だけです。我々は兄弟姉妹を望んでいない..それに応じて我々は\[{それは私たちが親に到達し、兄弟をバイパスする方法です。私たちは欲しい鎖を持っています。

それを終了します。

var rx2 = new RegExp('{"x":"([\\w-]+)(?=[":,\\.\\w-]+\\[{[\\[{}":,\\.\\w-]+' + regExpEscape(result[0]) + ')',"g"); 
while (!!(rar = rx2.exec(js))){result.push(rar[1])} 

これはそうです。 JSONオブジェクトの深さに関係なく、

+0

提案の皆さん、ありがとう。親IDとその他の情報を持つSQLテーブルに同じJSONデータが格納されています。実際には、データベース内のデータを検索し、レコードをリレーショナルデータとして返す既存のSQLストアドプロシージャを使用しました。このリレーショナルデータをJSON文字列に変換して検索結果を表示するには、C#コードを使用します。 – user2272865

関連する問題