Finding JSON path inside object [duplicate] - javascript

This question already has answers here:
Convert string in dot notation to get the object reference [duplicate]
(6 answers)
Closed 8 years ago.
How to check in an JSON object, the input path is present or not?
var obj = {
"schemaOne": {
"name": "abc",
"Path": "i.abc",
"count": 5347,
"subFolders": [
]
},
"schemaTwo": {
"name": "cde",
"Path": "i.cde",
"count": 0,
"subFolders": [
{
"name": "efg",
"Path": "",
"count": 0,
"subFolders": [
]
},
{
"name": "hij",
"Path": "i.hij",
"count": 1,
"subFolders": [
]
}
]
}
}
var inputpath = "obj.count";
After doing several research I came across below code. Here in this code, o.Path is known to the user. But I want to modify the code so tat dynamically check obj.count is present in JSON object or not?
function upd(o, path, count) {
if (o.Path == path) {
o.count = count;
} else {
var arr;
if (Array.isArray(o)) arr = o;
else if (o.subFolders) arr = o.subFolders;
else return;
for(var j=0; j < arr.length; j++) {
upd(arr[j], path, count);
}
}
}

Your question isn't very clear, neither the use case. As someone told u, obj is a JavaScript object, not a JSON.
If I understood correctly, you want to check if a path, espressed as string (such as "obj.count") exists in that object.
A very fast but not safe solution (eval is evil and should be avoided almost in every case) could be:
if(eval(inputpath)){
//... do something
}
In alternative, I suggest you to write a function that gets an object and a string (path) as parameter, parses the string path and check if the object contains such path.
Start from here: Accessing nested JavaScript objects with string key

Related

Splicing JSON object from array [duplicate]

This question already has answers here:
How to filter object array based on attributes?
(21 answers)
Closed 8 months ago.
I have tried splicing my json file using a for loop
JSON file:
[
{
"name":"Billy Jean",
"age":"52",
"sex":"F",
},
{
"name":"Bob Semple",
"age":"32",
"sex":"M",
} there are more....
]
What I have tried (i imported it and called it contactList)
for(let i = 0 ; i < contactList.length ; i++){
if(contactlist.age > 40) {
contactList.splice(i, 1);
}
}
if i run the code and check the output nothing changes in my JSON file
You can create a new array using Array.prototype.filter() combined with Destructuring assignment
Notice that age property it's of type string and should be compared as number using unary plus (+) operator
Code:
const data = [{
"name": "Billy Jean",
"age": "52",
"sex": "F",
},
{
"name": "Bob Semple",
"age": "32",
"sex": "M",
}
]
const result = data.filter(({ age }) => +age > 40)
console.log(result)

Find index of an object in an arrray of objects [duplicate]

This question already has answers here:
How can I get the index of an object by its property in JavaScript?
(22 answers)
Closed 1 year ago.
I have an array that looks like this:
const arr = [
{ "-MrUU6N2pi7aCwJoqCzP": { "name": "test", "brand": "test", "id": 1 } },
{ "-MrUUB4PcPD5G45NGb-y": { "name": "test2", "brand": "test2", "id": 2 } }
]
How do I find the index of the object with the key "-MrUUB4PcPD5G45NGb-y" for example?
You can use findIndex() and look at the Object.keys() for each object in the array to see if the key you want is in that keys array
const arr = [
{"-MrUU6N2pi7aCwJoqCzP":{"name":"test","brand":"test","id":1}},
{"-MrUUB4PcPD5G45NGb-y":{"name":"test2","brand":"test2","id":2}}
],
keyWanted = "-MrUUB4PcPD5G45NGb-y",
idx = arr.findIndex(e => Object.keys(e).includes(keyWanted))
console.log('Index =', idx)

How can javascript extract specified key value from json blob with many nested values? [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 1 year ago.
I have an https query which returns a json blob in the following format:
{
"metric_data": {
"from": "2021-12-09T01:25:32+00:00",
"to": "2021-12-09T01:55:32+00:00",
"metrics_not_found": [],
"metrics_found": [
"Mobile/Crash/All"
],
"metrics": [
{
"name": "Mobile/Crash/All",
"timeslices": [
{
"from": "2021-12-09T01:24:00+00:00",
"to": "2021-12-09T01:54:00+00:00",
"values": {
"call_count": 5
}
}
]
}
]
}
}
I want to find and extract the value for call_count. What is the best way to do that with Javascript? The following code will actually print out all the json values, including the call_count but all my efforts to just grab the value for call_count are failing.
var json = `{
"metric_data": {
"from": "2021-12-09T01:25:32+00:00",
"to": "2021-12-09T01:55:32+00:00",
"metrics_not_found": [],
"metrics_found": [
"Mobile/Crash/All"
],
"metrics": [
{
"name": "Mobile/Crash/All",
"timeslices": [
{
"from": "2021-12-09T01:24:00+00:00",
"to": "2021-12-09T01:54:00+00:00",
"values": {
"call_count": 5
}
}
]
}
]
}
}`;
// Convert a JSON object to a Javascript object
var obj = JSON.parse(json);
// This function prints nested values
function printValues(obj) {
for(var k in obj) {
if(obj[k] instanceof Object) {
printValues(obj[k]);
} else {
document.write(obj[k] + "<br>");
};
}
};
// Printing all the values from the resulting object
printValues(obj);
document.write("<hr>");
// This is where I fail as I try to print a single value.
document.write(obj["metrics"]["call_count"] + "<br>");
Any feedback would be much appreciated!
Yes, well first there is the metric_data attribute you have ignored. Then metrics is an array of objects. Your snippet has one object in it, but it's still an array of objects. An object in that array has timeslices, which is an array of objects.
var json = `{
"metric_data": {
"from": "2021-12-09T01:25:32+00:00",
"to": "2021-12-09T01:55:32+00:00",
"metrics_not_found": [],
"metrics_found": [
"Mobile/Crash/All"
],
"metrics": [
{
"name": "Mobile/Crash/All",
"timeslices": [
{
"from": "2021-12-09T01:24:00+00:00",
"to": "2021-12-09T01:54:00+00:00",
"values": {
"call_count": 5
}
}
]
}
]
}
}`;
// Convert a JSON object to a Javascript object
var obj = JSON.parse(json);
console.log(obj.metric_data.metrics[0].timeslices[0].values.call_count);

Extract image value from an object [duplicate]

This question already has answers here:
JavaScript object: access variable property by name as string [duplicate]
(3 answers)
Closed 5 years ago.
I have an object like this :
var obj = [
{
"id": 728,
"title": "A long day",
"images": {
"illustration": {
"title": "Preview",
"16x9": {
"1248x702": "https://example.com/image/225944d77559.jpg",
"1920x1080": "https://example.com/image/4546b05422594.jpg"
}
}
}
}
];
I'm trying for some time to get the 1920x1080 value, but without success :
alert(obj[0].title); //works
alert(obj[0].images.illustration.title); // works
alert(obj[0].images.illustration.16x9.1920x1080); // doesn't work and break the code
alert(obj[0].images.illustration.'16x9'.'1920x1080'); // doesn't work and break the code
I need your help. What should I do to get the 1920x1080 entry correctly ?
Use bracket:
var obj = [
{
"id": 728,
"title": "A long day",
"images": {
"illustration": {
"title": "Preview",
"16x9": {
"1248x702": "https://example.com/image/225944d77559.jpg",
"1920x1080": "https://example.com/image/4546b05422594.jpg"
}
}
}
}
];
console.log(obj[0].images.illustration['16x9']['1920x1080']);
Try this,
alert(obj[0].images.illustration['16x9']['1920x1080']);
You should write next:
obj[0].images.illustration['16x9']['1920x1080']
In JS if you have object key with specific sympols you should wrap this in Square brackets ['1920x1080'], its like you get elemet from array.

replace multiple values in json/jsObject/string

I have a response from a web service and want to replace some values in the response with my custom values.
One way is to write a tree traverser and then check for the value and replace with my custom value
so the response is some what like this:
[
{
"name": "n1",
"value": "v1",
"children": [
{
"name": "n2",
"value": "v2"
}
]
},
{
"name": "n3",
"value": "v3"
}
]
now my custom map is like this
const map = {
"v1": "v11",
"v2": "v22",
"v3": "v33"
};
All I want is
[
{
"name": "n1",
"value": "v11",
"children": [
{
"name": "n2",
"value": "v22"
}
]
},
{
"name": "n3",
"value": "v33"
}
]
I was thinking if I could stringify my response and then replace values using a custom build regex from my map of values.
Will it be faster as compared to tree traverser?
If yes, how should I do that?
somewhat like this
originalString.replace(regexp, function (replacement))
The tree traversal is faster
Note that some things could be done more efficiently in the regex implementation but I still think there are some more bottlenecks to explain.
Why the regex is slow:
There are probably many more reasons why the regex is slower but I'll explain at least one significant reason:
When you're using regex to find and replace, you're using creating new strings every time and performing your matches every time. Regex expressions can be very expensive and my implementation isn't particularly cheap.
Why is the tree traversal faster:
In the tree traversal, I'm mutating the object directly. This doesn't require creating new string objects or any new objects at all. We're also not performing a full search on the whole string every time as well.
RESULTS
run the performance test below. The test using console.time to record how long it takes. See the the tree traversal is much faster.
function usingRegex(obj, map) {
return JSON.parse(Object.keys(map).map(oldValue => ({
oldValue,
newValue: map[oldValue]
})).reduce((json, {
oldValue,
newValue
}) => {
return json.replace(
new RegExp(`"value":"(${oldValue})"`),
() => `"value":"${newValue}"`
);
}, JSON.stringify(obj)));
}
function usingTree(obj, map) {
function traverse(children) {
for (let item of children) {
if (item && item.value) {
// get a value from a JS object is O(1)!
item.value = map[item.value];
}
if (item && item.children) {
traverse(item.children)
}
}
}
traverse(obj);
return obj; // mutates
}
const obj = JSON.parse(`[
{
"name": "n1",
"value": "v1",
"children": [
{
"name": "n2",
"value": "v2"
}
]
},
{
"name": "n3",
"value": "v3"
}
]`);
const map = {
"v1": "v11",
"v2": "v22",
"v3": "v33"
};
// show that each function is working first
console.log('== TEST THE FUNCTIONS ==');
console.log('usingRegex', usingRegex(obj, map));
console.log('usingTree', usingTree(obj, map));
const iterations = 10000; // ten thousand
console.log('== DO 10000 ITERATIONS ==');
console.time('regex implementation');
for (let i = 0; i < iterations; i += 1) {
usingRegex(obj, map);
}
console.timeEnd('regex implementation');
console.time('tree implementation');
for (let i = 0; i < iterations; i += 1) {
usingTree(obj, map);
}
console.timeEnd('tree implementation');
Will it be faster as compared to tree traverser?
I don't know. I think it would depend on the size of the input, and the size of the replacement map. You could run some tests at JSPerf.com.
If yes, how should I do that?
It's fairly easy to do with a regex-based string replacement if the values you are replacing don't need any special escaping or whatever. Something like this:
const input = [
{
"name": "n1",
"value": "v1",
"children": [
{
"name": "n2",
"value": "v2"
}
]
},
{
"name": "n3",
"value": "v3"
}
];
const map = {
"v1": "v11",
"v2": "v22",
"v3": "v33"
};
// create a regex that matches any of the map keys, adding ':' and quotes
// to be sure to match whole property values and not property names
const regex = new RegExp(':\\s*"(' + Object.keys(map).join('|') + ')"', 'g');
// NOTE: if you've received this data as JSON then do the replacement
// *before* parsing it, don't parse it then restringify it then reparse it.
const json = JSON.stringify(input);
const result = JSON.parse(
json.replace(regex, function(m, key) { return ': "' + map[key] + '"'; })
);
console.log(result);
definitely traverser go faster as string replace means travels against each characters in the final string as opposed to iterator that can skips no necessarily item.

Categories

Resources