1

I have one strange requirement to fetch the values from JSON object by values, for example in the below json object, two arrays are there in that if I pass value as Steve instead of full value like Steve Jon, How do I loop my whole json object and find the matching object in the entire json object. My json object is very big and please suggest me any good way to loop entire object without killing performance. I have checked JSONPath expression but its not working

Thanks in advance

grouped_people: {
    'friends': [
        {name: 'Steve Jon', country: 'NZ'},
        {name: 'Jane Ken', country: 'US'},
        {name: 'Mike Jhon', country: 'AU'},
        {name: 'Mary Mani', country: 'NZ'},
    ],
    'enemies': [
        {name: 'Evil Steve', country: 'AU'},
        {name: 'Betty', country: 'NZ'},
    ]
}
Varun Sharma
  • 1,602
  • 1
  • 13
  • 37

3 Answers3

0

You can use a recursive function to find the object which contains the given value as below.

var grouped_people = {
  'friends': [{
      name: 'Steve Jon',
      country: 'NZ'
    },
    {
      name: 'Jane Ken',
      country: 'US'
    },
    {
      name: 'Mike Jhon',
      country: 'AU'
    },
    {
      name: 'Mary Mani',
      country: 'NZ'
    },
  ],
  'enemies': [{
      name: 'Evil steve',
      country: 'AU'
    },
    {
      name: 'Betty',
      country: 'NZ'
    },
  ]
};

//Recursive function to search text in the object
function findObject(obj, text, callback) {
  for (var k in obj) {
    if (typeof obj[k] == "object" && obj[k] !== null) {
      findObject(obj[k], text, callback);
    } else {
      if (obj[k].toLowerCase().indexOf(text.toLowerCase()) !== -1) {
        callback(obj);            
      }
    }
  }
}


findObject(grouped_people, "Steve", function(obj) {
  //All matched objects will return here.
  console.log(obj);
});
Thusitha
  • 3,393
  • 3
  • 21
  • 33
  • Looks good and as expected but challenge will come for big json object – Mallikarjun Hampannavar Sep 27 '17 at 05:19
  • @MallikarjunHampannavar There is no other solution rather than going through the whole object since you want the object as the output. :( – Thusitha Sep 27 '17 at 05:26
  • Yes you are right bro.. I am checking this for my big object lets see the performance – Mallikarjun Hampannavar Sep 27 '17 at 05:39
  • @MallikarjunHampannavar You can vote it up and make it as the correct answer if it helped you in anyway. – Thusitha Sep 27 '17 at 05:41
  • Yes this helped me but im modifying it for my requirement and also Im struck in case sensitive and if the value does not match.. if possible can you also try to modify – Mallikarjun Hampannavar Sep 27 '17 at 06:05
  • @MallikarjunHampannavar I modified it for case insensitivity. Small change ;) – Thusitha Sep 27 '17 at 06:22
  • This answer is working fine at some extent.. But whenever we find the same text in the same object.. it will give me two object output please check this fiddle https://jsfiddle.net/h19qswv7/ here im trying to search "Steve" text but output is two times coming.. Is there anything turn around in the existing method.. – Mallikarjun Hampannavar Oct 10 '17 at 07:33
  • @MallikarjunHampannavar The current implementation is to search the given text in any given key value pair. Since the `Steve` text is used in both country and name keys the same object will output as two objects. You can either filter the final output to contain unique objects or just check the text inside a specific key either `country` or `name`. – Thusitha Oct 10 '17 at 09:32
0

I think blow function(from Google's Angular project) maybe help you:

/* Seach in Object */

var comparator = function(obj, text) {
if (obj && text && typeof obj === 'object' && typeof text === 'object') {
    for (var objKey in obj) {
        if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
                comparator(obj[objKey], text[objKey])) {
            return true;
        }
    }
    return false;
}
text = ('' + text).toLowerCase();
return ('' + obj).toLowerCase().indexOf(text) > -1;
};

var search = function(obj, text) {
if (typeof text == 'string' && text.charAt(0) === '!') {
    return !search(obj, text.substr(1));
}
switch (typeof obj) {
    case "boolean":
    case "number":
    case "string":
        return comparator(obj, text);
    case "object":
        switch (typeof text) {
            case "object":
                return comparator(obj, text);
            default:
                for (var objKey in obj) {
                    if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
                        return true;
                    }
                }
                break;
        }
        return false;
    case "array":
        for (var i = 0; i < obj.length; i++) {
            if (search(obj[i], text)) {
                return true;
            }
        }
        return false;
    default:
        return false;
}
};

See this post.

n.y
  • 3,343
  • 3
  • 35
  • 54
0

Based on your object, you can do this :

for (var key in obj) {
  if (obj.hasOwnProperty(key)) {
  for (var subKey in obj[key]) {        
    if(obj[key][subKey].name.toLowerCase().search(keyword)!=-1){
        alert('The keyword exist')
        return true;
    }
  }       

  }
    alert('not found');
    return false;   
}

I assume you pass the keyword by a form, for example you can pass it to a method like below :

<input type="text" id="keyword" placeholder="Enter Keyword" />
<input type="button" onclick="find(keyword.value)" value="find" />

I made an example for you here ( Update for case-insensitive search ) :

https://jsfiddle.net/emilvr/9o8s2680/2/

Emad Dehnavi
  • 3,262
  • 4
  • 19
  • 44