49

我的应用程序中有一个 JSON 字符串/对象。

{"list": [
    {"name":"my Name","id":12,"type":"car owner"},
    {"name":"my Name2","id":13,"type":"car owner2"},
    {"name":"my Name4","id":14,"type":"car owner3"},
    {"name":"my Name4","id":15,"type":"car owner5"}
]}

我的应用程序中有一个过滤器框,当我在该框中输入名称时,我们必须过滤对象并显示结果。

例如,如果用户键入“姓名”并点击搜索,那么我们必须在 JSON 对象中搜索全名并返回数组,就像 MySQL 搜索一样...

我的问题是用字符串过滤json对象并返回数组......

4

8 回答 8

53

您可以遍历数组并找到匹配项:

var results = [];
var searchField = "name";
var searchVal = "my Name";
for (var i=0 ; i < obj.list.length ; i++)
{
    if (obj.list[i][searchField] == searchVal) {
        results.push(obj.list[i]);
    }
}
于 2012-05-21T04:49:32.857 回答
45

如果您的问题是,是否有一些内置的东西可以为您进行搜索,那么不,没有。String#indexOf您基本上使用正则表达式或正则表达式遍历数组来测试字符串。

对于循环,您至少有三个选择:

  1. 一个无聊的老for循环。

  2. 在启用 ES5 的环境(或使用 shim)上,Array#filter.

  3. 因为您使用的是 jQuery jQuery.map,.

无聊的旧for循环示例:

function search(source, name) {
    var results = [];
    var index;
    var entry;

    name = name.toUpperCase();
    for (index = 0; index < source.length; ++index) {
        entry = source[index];
        if (entry && entry.name && entry.name.toUpperCase().indexOf(name) !== -1) {
            results.push(entry);
        }
    }

    return results;
}

您将在哪里调用它obj.listassource和所需的名称片段 as name

或者,如果有任何可能存在空白条目或没有名称的条目,请将其更改if为:

        if (entry && entry.name && entry.name.toUpperCase().indexOf(name) !== -1) {

Array#filter例子:

function search(source, name) {
    var results;

    name = name.toUpperCase();
    results = source.filter(function(entry) {
        return entry.name.toUpperCase().indexOf(name) !== -1;
    });
    return results;
}

同样,如果有任何可能有空白条目(例如,undefined与缺失相反;filter将跳过缺失的条目),将内部返回更改为:

        return entry && entry.name && entry.name.toUpperCase().indexOf(name) !== -1;

jQuery.map示例(这里我假设jQuery=$通常是这种情况;如果您正在使用,请更改$为):jQuerynoConflict

function search(source, name) {
    var results;

    name = name.toUpperCase();
    results = $.map(source, function(entry) {
        var match = entry.name.toUpperCase().indexOf(name) !== -1;
        return match ? entry : null;
    });
    return results;
}

(再一次,entry && entry.name &&如有必要,请在此处添加。)

于 2012-05-21T04:48:47.867 回答
17

您可以简单地将数据保存在变量中,然后使用 JavaScript 的 find(获取单个记录对象)或 filter(获取单个记录数组)方法。

例如 :-

let data = {
 "list": [
   {"name":"my Name","id":12,"type":"car owner"},
   {"name":"my Name2","id":13,"type":"car owner2"},
   {"name":"my Name4","id":14,"type":"car owner3"},
   {"name":"my Name4","id":15,"type":"car owner5"}
]}

现在使用以下命令 onkeyup 或输入

获取单个对象

data.list.find( record => record.name === "my Name")

获取单个数组对象

data.list.filter( record => record.name === "my Name")
于 2020-02-05T04:15:15.707 回答
2

使用PaulGuojSQL,一个使用 javascript 的类似 SQL 的数据库。例如:

var db = new jSQL();
db.create('dbname', testListData).use('dbname');
var data = db.select('*').where(function(o) {
    return o.name == 'Jacking';
}).listAll();
于 2012-05-21T05:12:56.810 回答
2

我调整了正则表达式以使用 JSON。

首先,对 JSON 对象进行字符串化。然后,您需要存储匹配子字符串的开始和长度。例如:

"matched".search("ch") // yields 3

对于 JSON 字符串,它的工作原理完全相同(除非您明确搜索逗号和大括号,在这种情况下,我建议您在执行正则表达式之前先对 JSON 对象进行一些转换(例如:、{、})。

接下来,您需要重构 JSON 对象。我编写的算法通过从匹配索引递归地向后检测 JSON 语法来做到这一点。例如,伪代码可能如下所示:

find the next key preceding the match index, call this theKey
then find the number of all occurrences of this key preceding theKey, call this theNumber
using the number of occurrences of all keys with same name as theKey up to position of theKey, traverse the object until keys named theKey has been discovered theNumber times
return this object called parentChain

有了这些信息,就可以使用正则表达式来过滤 JSON 对象以返回键、值和父对象链。

您可以在http://json.spiritway.co/看到我编写的库和代码

于 2015-03-27T19:36:52.007 回答
1

如果您在应用程序中的多个位置执行此操作,则使用客户端 JSON 数据库是有意义的,因为创建由 array.filter() 调用的自定义搜索函数比其他方法更麻烦且不易维护。

查看 ForerunnerDB,它为您提供了一个非常强大的客户端 JSON 数据库系统,并包括一个非常简单的查询语言来帮助您完成您正在寻找的事情:

// Create a new instance of ForerunnerDB and then ask for a database
var fdb = new ForerunnerDB(),
    db = fdb.db('myTestDatabase'),
    coll;

// Create our new collection (like a MySQL table) and change the default
// primary key from "_id" to "id"
coll = db.collection('myCollection', {primaryKey: 'id'});

// Insert our records into the collection
coll.insert([
    {"name":"my Name","id":12,"type":"car owner"},
    {"name":"my Name2","id":13,"type":"car owner2"},
    {"name":"my Name4","id":14,"type":"car owner3"},
    {"name":"my Name4","id":15,"type":"car owner5"}
]);

// Search the collection for the string "my nam" as a case insensitive
// regular expression - this search will match all records because every
// name field has the text "my Nam" in it
var searchResultArray = coll.find({
    name: /my nam/i
});

console.log(searchResultArray);

/* Outputs
[
    {"name":"my Name","id":12,"type":"car owner"},
    {"name":"my Name2","id":13,"type":"car owner2"},
    {"name":"my Name4","id":14,"type":"car owner3"},
    {"name":"my Name4","id":15,"type":"car owner5"}
]
*/

免责声明:我是 ForerunnerDB 的开发者。

于 2016-12-07T15:34:17.337 回答
0

这是使用object-scan的迭代解决方案。好处是你可以很容易地在过滤器函数中做其他处理,并以更易读的格式指定路径。但是,引入依赖项需要权衡取舍,因此它实际上取决于您的用例。

// const objectScan = require('object-scan');

const search = (haystack, k, v) => objectScan([`list[*].${k}`], {
  rtn: 'parent',
  filterFn: ({ value }) => value === v
})(haystack);

const obj = { list: [ { name: 'my Name', id: 12, type: 'car owner' }, { name: 'my Name2', id: 13, type: 'car owner2' }, { name: 'my Name4', id: 14, type: 'car owner3' }, { name: 'my Name4', id: 15, type: 'car owner5' } ] };

console.log(search(obj, 'name', 'my Name'));
// => [ { name: 'my Name', id: 12, type: 'car owner' } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>

免责声明:我是对象扫描的作者

于 2020-11-18T05:58:48.877 回答
-2

你可以试试这个:

function search(data,search) {
    var obj = [], index=0;
    for(var i=0; i<data.length; i++) {
      for(key in data[i]){
         if(data[i][key].toString().toLowerCase().indexOf(search.toLowerCase())!=-1) {
                obj[index] = data[i];
                index++;
                break;
         }
     }
     return obj;
}
console.log(search(obj.list,'my Name'));
于 2017-10-19T09:20:15.150 回答