使用jQuery或Javascript搜索嵌套的JSON

时间:2016-03-24 07:45:17

标签: javascript jquery json treeview

我有一个大的嵌套JSON文件,我用它来绑定到树视图。我想通过文本搜索这个树视图数据源并获取匹配的所有节点,直到它的父节点,以便我可以保留树结构。所以我要说我有一个类似下面的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”并且它应该返回到具有相同嵌套的对象下面:

child-3(因为匹配),child-2(child-3的父级)和root-1(child-2的父级)。

现在我可以使用这个JSON绑定到我的树视图。

3 个答案:

答案 0 :(得分:1)

实际上,与任意文本字符串不同,一旦字符串化,JSON数据就会产生一个非常规则的结构化字符串,因此我们可以应用很酷的正则表达式,将代码缩小为2~3个字符串。我不确定这个或递归或迭代是否更有效。我稍后会试一试。

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"]

故事讲述部分:

我们可以通过两个步骤获得我们追求的结果。让我们看看

为了检查1.3是否存在并获取x属性的值(名称),我们可以使用/{"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. 遇到[字符时会到达父元素。
  3. 酷让我们继续。我有一点脑子融化了这个并想出了/{"x":"([\w-]+)(?=[":,\.\w-]+\[{[\[{}":,\.\w-]+child-3)/g好吧,它看起来有点神秘,但实际上非常简单。让我来看看。它由两部分组成xxx(yyy)必须先于(?= [允许的字符]后跟[{then [一些更多允许的字符]后跟“child-3”。)因为我们从不允许]字符永远不会找到任何一个孩子,但只有父母和兄弟姐妹。我们不想要兄弟姐妹..因此我们有\[{这就是我们如何找到父母并绕过兄弟姐妹。我们有了通缉链。

    让我们完成它;

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

    这似乎就是这样。无论您的JSON对象有多深,都可以获得。

答案 1 :(得分:0)

此提议迭代一个可能的数组,并为具有其前任节点的数组构建每个级别,如果找到search,则将路径推送到结果。迭代适用于短路。对于下一个级别,使用新的基础和实际节点的前一个路径再次调用该函数。

&#13;
&#13;
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>');
&#13;
&#13;
&#13;

答案 2 :(得分: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];
}