[javascript] JSON find in JavaScript

Is there a better way other than looping to find data in JSON? It's for edit and delete.

for(var k in objJsonResp) {
  if (objJsonResp[k].txtId == id) {
    if (action == 'delete') {
      objJsonResp.splice(k,1);
    } else {
      objJsonResp[k] = newVal;
    }
    break;
  }
}

The data is arranged as list of maps. Like:

[
  {id:value, pId:value, cId:value,...},
  {id:value, pId:value, cId:value,...},
  ...
]

This question is related to javascript json search

The answer is


Zapping - you can use this javascript lib; DefiantJS. There is no need to restructure JSON data into objects to ease searching. Instead, you can search the JSON structure with an XPath expression like this:

    var data = [
   {
      "id": "one",
      "pId": "foo1",
      "cId": "bar1"
   },
   {
      "id": "two",
      "pId": "foo2",
      "cId": "bar2"
   },
   {
      "id": "three",
      "pId": "foo3",
      "cId": "bar3"
   }
],
res = JSON.search( data, '//*[id="one"]' );

console.log( res[0].cId );
// 'bar1'

DefiantJS extends the global object JSON with a new method; "search" which returns array with the matches (empty array if none were found). You can try it out yourself by pasting your JSON data and testing different XPath queries here:

http://www.defiantjs.com/#xpath_evaluator

XPath is, as you know, a standardised query language.


I had come across this issue for a complex model with several nested objects. A good example of what I was looking at doing would be this: Lets say you have a polaroid of yourself. And that picture is then put into a trunk of a car. The car is inside of a large crate. The crate is in the hold of a large ship with many other crates. I had to search the hold, look in the crates, check the trunk, and then look for an existing picture of me.

I could not find any good solutions online to use, and using .filter() only works on arrays. Most solutions suggested just checking to see if model["yourpicture"] existed. This was very undesirable because, from the example, that would only search the hold of the ship and I needed a way to get them from farther down the rabbit hole.

This is the recursive solution I made. In comments, I confirmed from T.J. Crowder that a recursive version would be required. I thought I would share it in case anyone came across a similar complex situation.

function ContainsKeyValue( obj, key, value ){
    if( obj[key] === value ) return true;
    for( all in obj )
    {
        if( obj[all] != null && obj[all][key] === value ){
            return true;
        }
        if( typeof obj[all] == "object" && obj[all]!= null ){
            var found = ContainsKeyValue( obj[all], key, value );
            if( found == true ) return true;
        }
    }
    return false;
}

This will start from a given object inside of the graph, and recurse down any objects found. I use it like this:

var liveData = [];
for( var items in viewmodel.Crates )
{
    if( ContainsKeyValue( viewmodel.Crates[items], "PictureId", 6 ) === true )
    {
        liveData.push( viewmodel.Crates[items] );
    }
}

Which will produce an array of the Crates which contained my picture.


Ok. So, I know this is an old post, but perhaps this can help someone else. This is not backwards compatible, but that's almost irrelevant since Internet Explorer is being made redundant.

Easiest way to do exactly what is wanted:

function findInJson(objJsonResp, key, value, aType){        
     if(aType=="edit"){
        return objJsonResp.find(x=> x[key] == value);
     }else{//delete
         var a =objJsonResp.find(x=> x[key] == value);
         objJsonResp.splice(objJsonResp.indexOf(a),1);
     }
}

It will return the item you want to edit if you supply 'edit' as the type. Supply anything else, or nothing, and it assumes delete. You can flip the conditionals if you'd prefer.


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 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.


General Solution

We use object-scan for a lot of data processing. It has some nice properties, especially traversing in delete safe order. Here is how one could implement find, delete and replace for your question.

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

const tool = (() => {
  const scanner = objectScan(['[*]'], {
    abort: true,
    rtn: 'bool',
    filterFn: ({
      value, parent, property, context
    }) => {
      if (value.id === context.id) {
        context.fn({ value, parent, property });
        return true;
      }
      return false;
    }
  });
  return {
    add: (data, id, obj) => scanner(data, { id, fn: ({ parent, property }) => parent.splice(property + 1, 0, obj) }),
    del: (data, id) => scanner(data, { id, fn: ({ parent, property }) => parent.splice(property, 1) }),
    mod: (data, id, prop, v = undefined) => scanner(data, {
      id,
      fn: ({ value }) => {
        if (value !== undefined) {
          value[prop] = v;
        } else {
          delete value[prop];
        }
      }
    })
  };
})();

// -------------------------------

const data = [ { id: 'one', pId: 'foo1', cId: 'bar1' }, { id: 'three', pId: 'foo3', cId: 'bar3' } ];
const toAdd = { id: 'two', pId: 'foo2', cId: 'bar2' };

const exec = (fn) => {
  console.log('---------------');
  console.log(fn.toString());
  console.log(fn());
  console.log(data);
};

exec(() => tool.add(data, 'one', toAdd));
exec(() => tool.mod(data, 'one', 'pId', 'zzz'));
exec(() => tool.mod(data, 'one', 'other', 'test'));
exec(() => tool.mod(data, 'one', 'gone', 'delete me'));
exec(() => tool.mod(data, 'one', 'gone'));
exec(() => tool.del(data, 'three'));

// => ---------------
// => () => tool.add(data, 'one', toAdd)
// => true
// => [ { id: 'one', pId: 'foo1', cId: 'bar1' }, { id: 'two', pId: 'foo2', cId: 'bar2' }, { id: 'three', pId: 'foo3', cId: 'bar3' } ]
// => ---------------
// => () => tool.mod(data, 'one', 'pId', 'zzz')
// => true
// => [ { id: 'one', pId: 'zzz', cId: 'bar1' }, { id: 'two', pId: 'foo2', cId: 'bar2' }, { id: 'three', pId: 'foo3', cId: 'bar3' } ]
// => ---------------
// => () => tool.mod(data, 'one', 'other', 'test')
// => true
// => [ { id: 'one', pId: 'zzz', cId: 'bar1', other: 'test' }, { id: 'two', pId: 'foo2', cId: 'bar2' }, { id: 'three', pId: 'foo3', cId: 'bar3' } ]
// => ---------------
// => () => tool.mod(data, 'one', 'gone', 'delete me')
// => true
// => [ { id: 'one', pId: 'zzz', cId: 'bar1', other: 'test', gone: 'delete me' }, { id: 'two', pId: 'foo2', cId: 'bar2' }, { id: 'three', pId: 'foo3', cId: 'bar3' } ]
// => ---------------
// => () => tool.mod(data, 'one', 'gone')
// => true
// => [ { id: 'one', pId: 'zzz', cId: 'bar1', other: 'test', gone: undefined }, { id: 'two', pId: 'foo2', cId: 'bar2' }, { id: 'three', pId: 'foo3', cId: 'bar3' } ]
// => ---------------
// => () => tool.del(data, 'three')
// => true
// => [ { id: 'one', pId: 'zzz', cId: 'bar1', other: 'test', gone: undefined }, { id: 'two', pId: 'foo2', cId: 'bar2' } ]
_x000D_
.as-console-wrapper {max-height: 100% !important; top: 0}
_x000D_
<script src="https://bundle.run/[email protected]"></script>
_x000D_
_x000D_
_x000D_

Disclaimer: I'm the author of object-scan


If the JSON data in your array is sorted in some way, there are a variety of searches you could implement. However, if you're not dealing with a lot of data then you're probably going to be fine with an O(n) operation here (as you have). Anything else would probably be overkill.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to json

Use NSInteger as array index Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) HTTP POST with Json on Body - Flutter/Dart Importing json file in TypeScript json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 190) Angular 5 Service to read local .json file How to import JSON File into a TypeScript file? Use Async/Await with Axios in React.js Uncaught SyntaxError: Unexpected token u in JSON at position 0 how to remove json object key and value.? Find a file by name in Visual Studio Code Search all the occurrences of a string in the entire project in Android Studio Java List.contains(Object with field value equal to x) Trigger an action after selection select2 How can I search for a commit message on GitHub? SQL search multiple values in same field Find a string by searching all tables in SQL Server Management Studio 2008 Search File And Find Exact Match And Print Line? Java - Search for files in a directory How to put a delay on AngularJS instant search?