【问题标题】:Multiple keyword (that has regex) search through JSON通过 JSON 搜索多个关键字(具有正则表达式)
【发布时间】:2011-07-12 14:58:05
【问题描述】:

我有一些看起来像这样的 JSON:

"groups": [

  "group_id": "8",
  "group_name": "Building",
  "group_color": "00ff00"
},
{
  "group_id": "3",
  "group_name": "Building",
  "group_color": "8000ff"
},
{
  "group_id": "2",
  "group_name": "Sidewalk",
  "group_color": "ff0000"
},
{
  "group_id": "6",
  "group_name": "Parking Lot",
  "group_color": "00ffff"
},
{
  "group_id": "3",
  "group_name": "Commons",
  "group_color": "ff8000"
},
{
  "group_id": "5",
  "group_name": "Other",
  "group_color": "ff00ff"
}
]

当找到一个字段时,它会翻转一个布尔标志。
例如

for (var c=0; c<json.groups.length; c++) {
   inSearch = false;
   if(json.groups.group_id.match(query)!=null){
      inSearch = true;
   }
}

但是,如果 query = Building 则返回两个结果,所以我要做的是将 query = Building&amp;8 设置为仅返回第一个结果。

注意:查询也可以是一个正则表达式,我认为这是应该去的地方......

有什么想法吗?

编辑:有没有办法,比如说,将我的字符串分成几部分,然后根据该对象的两个不同部分匹配单个对象?那么根据 group_id 和 group_color 匹配第一个对象,还是根据 group_name 和 group_color 匹配?

【问题讨论】:

    标签: javascript json search


    【解决方案1】:

    对于目前的情况,这样的事情应该可以工作:

    data = JSON.parse('your_json');
    for (var i=0, j=data.length; i<j; i++){
        var inSearh = false;
        if(data[i].group_id===8 && data[i].group_name==="Something"){
        inSearch = true;
        break;
        }
    }
    

    对于更一般的情况,您可以将其包装在一个函数中:

    key_tester = function(jsonData,key1, value1, key2, value2){
        // Here jsonData is parsed JSON
        for(var i=0, j=jsonData.length; i<j; i++){
            var obj = jsonData[i];
            if(obj[key1] == value1 && obj[key2] == value2){
                return true; 
         }
         return false;
    }
    

    然后你可以像这样使用它:

    jsonData = JSON.parse('Your json');
    if (key_tester(jsonData, "group_id","8","group_name","building"))
       // Here goes your awesome code
    

    您可以扩展 key_tester 函数以包含更多键值对。

    这应该使我们免于使用正则表达式。

    【讨论】:

    • 感谢您的快速回答!我认为我的例子太具体了。您的代码适用于一种情况,但我试图使其更具动态性。那么如果我想让它匹配 group_id 和 group_color 呢?然后我又卡住了。
    • 在我看来,第二个答案可以完成这项工作。您所要做的只是将regsObj 更改为您想要搜索的任何内容。
    • 对,唯一的问题是字符串的顺序是任意的,那么我怎么知道字符串的前半部分是 group_id 还是前半部分是 group_color?从我们一直在谈论的内容来看,我认为它需要每次都进行某种类型的搜索并缩小搜索对象的范围?
    • 好的,这可能看起来不太优雅,但我正在更新我的答案,我认为应该可以解决您的问题。
    【解决方案2】:

    这是你的对象。

    var jsonObj = {
    "groups": [
        {
        "group_id": "8",
        "group_name": "Building",
        "group_color": "00ff00"},
    {
        "group_id": "3",
        "group_name": "Building",
        "group_color": "8000ff"},
    {
        "group_id": "2",
        "group_name": "Sidewalk",
        "group_color": "ff0000"},
    {
        "group_id": "6",
        "group_name": "Parking Lot",
        "group_color": "00ffff"},
    {
        "group_id": "3",
        "group_name": "Commons",
        "group_color": "ff8000"},
    {
        "group_id": "5",
        "group_name": "Other",
        "group_color": "ff00ff"}
    ]
    };
    

    此函数检查您的对象属性是否满足 regsObj 中定义的正则表达式。

    /**
     * Check that an obejct matches all the 
     * regexp defined in the regsObj
     */
     var matchRegObj = function(obj, regsObj) {
         var matched = false,
             regExp;
    
        for (var propName in regsObj) {
           regExp = regsObj[propName];
           matched = regExp.test(obj[propName]);
    
           if (matched !== true) {
              break;
           }
        }
    
        return matched;
    };
    

    函数测试返回你匹配的对象。

      /**
       * Return the first object matching all the regexp rule
       * defined in the regsObj.
       */
      var test = function(jsonObj, regsObj) {
        var matched = false,
            obj;
    
        for (var i = 0;  i < jsonObj.groups.length && !matched; i++) {
           obj = jsonObj.groups[i];
           matched = matchRegObj(obj, regsObj);
        }
    
        return (matched) ? obj : {};
    };
    

    在 regsObject 中,您定义组列表中的搜索对象必须满足的正则表达式。

    /**
     * regsObj is only a container of propertyName and regexp used to query the right object.
     */
    var regsObj = {
       "group_id" : "10",
       "group_name" : "Building" 
    };
    

    以这种方式搜索您的对象。

     /**
      * @param {Object} jsonObjyour Your json Object.
      * @param {Object} regObj The object holding all the regular expressions.
      * @return {Object} your matching object
      */
     var result = test(jsonObj, regsObj);
     console.dir(result);
    

    【讨论】:

    • 感谢您的快速回复!这肯定离我想要去的地方更近了,但我有与上面相同的问题:如果我想搜索 group_id 和 group_color 怎么办?我在帖子中添加了一个编辑以尝试澄清。
    • 您只需在 regsObject 中添加 group_color,方法如下: var regsObj = { "group_id" : "some_id", "group_color" "some_color" };
    【解决方案3】:

    SortingHat - 您可以使用这个 JS 库 DefiantJS (http://defiantjs.com),让它为您完成“繁重的工作”。这样,你的代码就更干净了,看起来像这样:

    var data = {
       "groups": [
          { "group_id": "8", "group_name": "Building",    "group_color": "00ff00" },
          { "group_id": "3", "group_name": "Building",    "group_color": "8000ff" },
          { "group_id": "2", "group_name": "Sidewalk",    "group_color": "ff0000" },
          { "group_id": "6", "group_name": "Parking Lot", "group_color": "00ffff" },
          { "group_id": "3", "group_name": "Commons",     "group_color": "ff8000" },
          { "group_id": "5", "group_name": "Other",       "group_color": "ff00ff" }
       ]
    },
    res = JSON.search( data, '//*[group_name="Building" and group_id=8]' )
    output = document.getElementById('output');
    
    output.innerHTML = JSON.stringify( res[0], null, '   ' );
    output.style.backgroundColor = '#'+ res[0].group_color;
    

    这是工作小提琴:
    http://jsfiddle.net/hbi99/3Ry4L/

    DefiantJS 使用“search”方法扩展全局对象 JSON - 使用该方法可以使用 XPath 表达式对 JSON 结构进行查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-22
      • 1970-01-01
      • 2019-11-17
      • 2021-12-22
      • 2012-08-13
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多