Reputation: 4082
I had a JSON string / object in my application.
{"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"}
]}
I had a filter box in my application, and when I type a name into that box, we have to filter the object and display the result.
For example, if the user types "name" and hits search, then we have to search full names in the JSON object and return the array, just like a MySQL search ...
My question is how can I filter the json object by a specified string and return the array....
Upvotes: 55
Views: 262787
Reputation: 3873
You can filter json object using any value from any property using this library Js-Search
Upvotes: 0
Reputation: 2181
Here is an iterative solution using object-scan. The advantage is that you can easily do other processing in the filter function and specify the paths in a more readable format. There is a trade-off in introducing a dependency though, so it really depends on your use case.
// 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/[email protected]"></script>
Disclaimer: I'm the author of object-scan
Upvotes: 0
Reputation: 2620
You can simply save your data in a variable and use find(to get single object of records) or filter(to get single array of records) method of JavaScript.
For example :-
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"}
]}
and now use below command onkeyup or enter
to get single object
data.list.find( record => record.name === "my Name")
to get single array object
data.list.filter( record => record.name === "my Name")
Upvotes: 20
Reputation: 11
You can try this:
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'));
Upvotes: -2
Reputation: 1075635
If your question is, is there some built-in thing that will do the search for you, then no, there isn't. You basically loop through the array using either String#indexOf
or a regular expression to test the strings.
For the loop, you have at least three choices:
A boring old for
loop.
On ES5-enabled environments (or with a shim), Array#filter
.
Because you're using jQuery, jQuery.map
.
Boring old for
loop example:
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;
}
Where you'd call that with obj.list
as source
and the desired name fragment as name
.
Or if there's any chance there are blank entries or entries without names, change the if
to:
if (entry && entry.name && entry.name.toUpperCase().indexOf(name) !== -1) {
Array#filter
example:
function search(source, name) {
var results;
name = name.toUpperCase();
results = source.filter(function(entry) {
return entry.name.toUpperCase().indexOf(name) !== -1;
});
return results;
}
And again, if any chance that there are blank entries (e.g., undefined
, as opposed to missing; filter
will skip missing entries), change the inner return to:
return entry && entry.name && entry.name.toUpperCase().indexOf(name) !== -1;
jQuery.map
example (here I'm assuming jQuery
= $
as is usually the case; change $
to jQuery
if you're using noConflict
):
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;
}
(And again, add entry && entry.name &&
in there if necessary.)
Upvotes: 48
Reputation: 6978
If you are doing this in more than one place in your application it would make sense to use a client-side JSON database because creating custom search functions that get called by array.filter() is messy and less maintainable than the alternative.
Check out ForerunnerDB which provides you with a very powerful client-side JSON database system and includes a very simple query language to help you do exactly what you are looking for:
// 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"}
]
*/
Disclaimer: I am the developer of ForerunnerDB.
Upvotes: 1
Reputation: 121
I adapted regex to work with JSON.
First, stringify the JSON object. Then, you need to store the starts and lengths of the matched substrings. For example:
"matched".search("ch") // yields 3
For a JSON string, this works exactly the same (unless you are searching explicitly for commas and curly brackets in which case I'd recommend some prior transform of your JSON object before performing regex (i.e. think :, {, }).
Next, you need to reconstruct the JSON object. The algorithm I authored does this by detecting JSON syntax by recursively going backwards from the match index. For instance, the pseudo code might look as follows:
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
With this information, it is possible to use regex to filter a JSON object to return the key, the value, and the parent object chain.
You can see the library and code I authored at http://json.spiritway.co/
Upvotes: 2
Reputation: 82
Use PaulGuo's jSQL, a SQL like database using javascript. For example:
var db = new jSQL();
db.create('dbname', testListData).use('dbname');
var data = db.select('*').where(function(o) {
return o.name == 'Jacking';
}).listAll();
Upvotes: 2
Reputation: 102793
You could just loop through the array and find the matches:
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]);
}
}
Upvotes: 60