I want to replace all object properties label to the property name text.
Given:
[
{
"value": "45a8",
"label": "45A8",
"children": [
{
"value": "45a8.ba08",
"label": "BA08",
"children": [
{
"value": "45a8.ba08.45a8",
"label": "45A8"
}
],
"checked": false
}
]
},
...
]
Needed:
[
{
"value": "45a8",
"text": "45A8",
"children": [
{
"value": "45a8.ba08",
"text": "BA08",
"children": [
{
"value": "45a8.ba08.45a8",
"text": "45A8"
}
],
"checked": false
}
]
},
...
]
You can first stringify the the data with JSON.stringify() then replace the string. Finally parse the string with JSON.parse():
var data = [
{
"value": "45a8",
"label": "45A8",
"children": [
{
"value": "45a8.ba08",
"label": "BA08",
"children": [
{
"value": "45a8.ba08.45a8",
"label": "45A8"
}
],
"checked": false
}
]
}
];
data = JSON.parse(JSON.stringify(data).replaceAll('"label"', '"text"'));
console.log(data);
Update: You can try using RegEx like the following way:
var data = [
{
"value": "45a8",
"label": "45A8",
"children": [
{
"value": "45a8.ba08",
"label": "BA08",
"children": [
{
"value": "45a8.ba08.45a8",
"label": "45A8"
}
],
"checked": false
}
]
}
];
var find = '"label"';
var re = new RegExp(find, 'g');
data = JSON.parse(JSON.stringify(data).replace(re, '"text"'));
console.log(data);
You can also browse through the keys and find the label key. Get it's value assign it to the new key i.e. text and delete the old key i.e. label.
let data = [
{
"value": "45a8",
"label": "45A8",
"children": [
{
"value": "45a8.ba08",
"label": "BA08",
"children": [
{
"value": "45a8.ba08.45a8",
"label": "45A8"
}
],
"checked": false
}
]
}
]
for (const key in data.keys()){
if(key === "label"){
data.text = data[key]
delete data.key
}
}
You can also do this with using recursion. It could be something like this:
const nestArr=[ { "value": "45a8", "label": "45A8", "children": [ { "value": "45a8.ba08", "label": "BA08", "children": [ { "value": "45a8.ba08.45a8", "label": "45A8" } ], "checked": false } ] }];
changeLabelToText=arr=>{
return arr.map(({label,...rest})=>{
if(rest.children) rest.children = changeLabelToText(rest.children);
return {text:label, ...rest}
})
};
console.log(changeLabelToText(nestArr));
Related
How to get the data value from the list, the size of the array, the main thing is not through the index, because the order of the arrays can change and I can get specific data from the code === "size". Unfortunately, the structure cannot be changed. It came to mind only through the filter, by index, but it is impossible
The result should be 100 150
https://jsoneditoronline.org/#left=cloud.b10638604c214b189f87747414e06035
[
[
"color",
{
"name": "Цвет",
"code": "color",
"list": [
{
"value": "Зеленый"
},
{
"value": "Красный"
}
]
}
],
[
"size",
{
"name": "Размер",
"code": "size",
"list": [
{
"value": "100"
},
{
"value": "150"
}
]
}
]
]
This data structure is terrible, but a quick fix could be something like this
const data = [
[
"color",
{
"name": "Цвет",
"code": "color",
"list": [
{
"value": "Зеленый"
},
{
"value": "Красный"
}
]
}
],
[
"size",
{
"name": "Размер",
"code": "size",
"list": [
{
"value": "100"
},
{
"value": "150"
}
]
}
]
]
const size = data.filter(element => element[1].code === 'size')[0][1].list.map(element => element.value)
console.log(size)
I have a JSON object that has an array as below
{
"objects": [
{
"severity": "LOW",
"tags": [
{
"key": "account",
"values": [
"account2"
]
},
{
"key": "accountId",
"values": [
"2"
]
}
],
"name": "object1"
},
{
"severity": "HIGH",
"tags": [
{
"key": "account",
"values": [
"account2"
]
},
{
"key": "accountId",
"values": [
"2"
]
}
],
"name": "object2"
},
{
"severity": "MEDIUM",
"tags": [
{
"key": "account",
"values": [
"account44"
]
},
{
"key": "accountId",
"values": [
"44"
]
}
],
"name": "object2"
},
{
"severity": "HIGH",
"tags": [
{
"key": "account",
"values": [
"account42"
]
},
{
"key": "accountId",
"values": [
"42"
]
}
],
"name": "object2"
}
]
}
I want to be able to go through the array using javascript and if severity is HIGH and acccountID matches 2 for example to set a warning. Even though account 2 might have a severity of LOW as shown, I still want to make the if condition true.
So something like if (objects.some(a =>(a.severity ==="LOW" && ...... or whatever better option there is.
You can loop through your object and match your properties like this
const data = { "objects": [ { "severity": "LOW", "tags": [ { "key": "account", "values": [ "account2" ] }, { "key": "accountId", "values": [ "2" ] } ], "name": "object1" }, { "severity": "HIGH", "tags": [ { "key": "account", "values": [ "account2" ] }, { "key": "accountId", "values": [ "2" ] } ], "name": "object2" }, { "severity": "MEDIUM", "tags": [ { "key": "account", "values": [ "account44" ] }, { "key": "accountId", "values": [ "44" ] } ], "name": "object2" }, { "severity": "HIGH", "tags": [ { "key": "account", "values": [ "account42" ] }, { "key": "accountId", "values": [ "42" ] } ], "name": "object2" } ] };
// Loop
for(let i = 0; i < data.objects.length; i++) {
// Set severity
const severity = data.objects[i].severity;
// Set ID
let id; for(let ii = 0; ii < data.objects[i].tags.length; ii++) if(data.objects[i].tags[ii].key === 'accountId') id = data.objects[i].tags[ii].values[0];
// Do logic here
if(severity === 'LOW' && id === '2') console.log(data.objects[i]);
}
If you're loop-avert:
if (objects.some(e => e.severity === severity || e.tags.some(t => t.key === 'accountId' && t.values.includes(accountId)))) {
...
For clarity, that closure is:
return e =>
e.severity === severity ||
e.tags.some(t =>
t.key === 'accountId' &&
t.values.includes(accountId));
e.g.
const j = { "objects": [ { "severity": "LOW", "tags": [ { "key": "account", "values": [ "account2" ] }, { "key": "accountId", "values": [ "2" ] } ], "name": "object1" }, { "severity": "HIGH", "tags": [ { "key": "account", "values": [ "account2" ] }, { "key": "accountId", "values": [ "2" ] } ], "name": "object2" }, { "severity": "MEDIUM", "tags": [ { "key": "account", "values": [ "account44" ] }, { "key": "accountId", "values": [ "44" ] } ], "name": "object2" }, { "severity": "HIGH", "tags": [ { "key": "account", "values": [ "account42" ] }, { "key": "accountId", "values": [ "42" ] } ], "name": "object2" } ] };
function condition(severity, accountId) {
return e =>
e.severity === severity ||
e.tags.some(t =>
t.key === 'accountId' &&
t.values.includes(accountId));
}
if (j.objects.some(condition('LOW', '2'))) {
console.log("warning: low || 2");
}
if (j.objects.some(condition('SUPER_HIGH', '4048'))) {
console.log("warning: super high || 4048");
}
Have this JSON object in JavaScript that comes from an API:
[
{
"id": 1,
"label": "Breakfast",
"subCategories": [
{
"id": 100,
"label": "Cereals, Muesli",
"items": [
{
"productId": "4fdddf1d-8d31-411d-a908-5edd68a775b7",
"label": "Bircher Muesli"
},
{
"productId": "000673e7-47ec-4dce-a940-ad4aacbd7d73",
"label": "Individual Cereals"
},
{
"productId": "0f739661-5531-4734-9dfd-e145b60667cc",
"label": "Organic Porridge Oats"
}
]
},
{
"id": 101,
"label": "Eggs, Omelettes",
"items": [
{
"productId": "6d608133-ab44-4f9d-ab8e-fc6a3f955397",
"label": "Crushed Avocado with Soughdough Toast"
},
{
"productId": "fcfe91ab-e9b1-4dc0-8c57-ffb9646e0658",
"label": "Crushed Avocado with Crispy Bacon"
},
{
"productId": "2a80e48b-76f6-4bda-abf3-ec8dc7bf1419",
"label": "Crushed Avocado with Smoked Salmon"
},
{
"productId": "ae35e949-abf3-4795-a5df-9af4250c2185",
"label": "Egg White Omelette"
}
]
}
]
},
{
"id": 2,
"label": "Light Lunch",
"subCategories": [
{
"id": 103,
"label": "Condiments",
"items": [
{
"productId": "25503a9b-b553-4b56-a152-49e4121cf4ae",
"label": "Butter"
},
{
"productId": "c1dd9761-f170-4e6a-a7d7-5519a4213874",
"label": "Jam"
}
]
},
{
"id": 104,
"label": "Yoghurts",
"items": [
{
"productId": "938fed24-6d4c-e0cd-8303-0fcd42c87be4",
"label": "Fruit Yoghurt",
},
{
"productId": "62137176-0966-4424-9093-51bd7871d31b",
"label": "Greek Yoghurt",
},
{
"productId": "307e59c4-b103-43d4-988c-75ee539d5d75",
"label": "Granola Parfait: Layers of Berries, Fruit Granola, Yoghurt & Honey",
}
]
}
]
}
]
I need to filter this array above with the search query (Eg: Greek) against the items.label property and have it returned the filtered outcome like below:
[
{
"id": 2,
"label": "Light Lunch",
"subCategories": [
{
"id": 104,
"label": "Yoghurts",
"items": [
{
"productId": "62137176-0966-4424-9093-51bd7871d31b",
"label": "Greek Yoghurt",
}
]
}
]
}
]
I've tried various implementation with filter() with nested some() as seen on StackOverflow but did not return the desired result. Currently this works but only the top level category is filtered and the nested subcategory only exist if there's a match for item.
var searchQuery="Greek";
var data=[]; //JSON omitted for brevity.
var result = data.filter(a=>{
return a.subCategories.some(b=> {
return b.items.some(c=> new RegExp(searchQuery,"i").test(c.label));
});
});
Any help would be greatly appreciated.
You can use Array.reduce for this, iterating first over each of the categories, then each of the subcategories, only adding the subcategory to the output if one of its items contains the search query, and then only adding the category to the output if one of the subcategories contains the search query:
const data = [{
"id": 1,
"label": "Breakfast",
"subCategories": [{
"id": 100,
"label": "Cereals, Muesli",
"items": [{
"productId": "4fdddf1d-8d31-411d-a908-5edd68a775b7",
"label": "Bircher Muesli"
},
{
"productId": "000673e7-47ec-4dce-a940-ad4aacbd7d73",
"label": "Individual Cereals"
},
{
"productId": "0f739661-5531-4734-9dfd-e145b60667cc",
"label": "Organic Porridge Oats"
}
]
},
{
"id": 101,
"label": "Eggs, Omelettes",
"items": [{
"productId": "6d608133-ab44-4f9d-ab8e-fc6a3f955397",
"label": "Crushed Avocado with Soughdough Toast"
},
{
"productId": "fcfe91ab-e9b1-4dc0-8c57-ffb9646e0658",
"label": "Crushed Avocado with Crispy Bacon"
},
{
"productId": "2a80e48b-76f6-4bda-abf3-ec8dc7bf1419",
"label": "Crushed Avocado with Smoked Salmon"
},
{
"productId": "ae35e949-abf3-4795-a5df-9af4250c2185",
"label": "Egg White Omelette"
}
]
}
]
},
{
"id": 2,
"label": "Light Lunch",
"subCategories": [{
"id": 103,
"label": "Condiments",
"items": [{
"productId": "25503a9b-b553-4b56-a152-49e4121cf4ae",
"label": "Butter"
},
{
"productId": "c1dd9761-f170-4e6a-a7d7-5519a4213874",
"label": "Jam"
}
]
},
{
"id": 104,
"label": "Yoghurts",
"items": [{
"productId": "938fed24-6d4c-e0cd-8303-0fcd42c87be4",
"label": "Fruit Yoghurt",
},
{
"productId": "62137176-0966-4424-9093-51bd7871d31b",
"label": "Greek Yoghurt",
},
{
"productId": "307e59c4-b103-43d4-988c-75ee539d5d75",
"label": "Granola Parfait: Layers of Berries, Fruit Granola, Yoghurt & Honey",
}
]
}
]
}
];
const searchQuery = "Greek";
const regex = new RegExp(searchQuery, "i");
const result = data.reduce((cats, cat) => {
cat.subCategories = cat.subCategories.reduce((subs, sub) => {
sub.items = sub.items.filter(item => regex.test(item.label));
if (sub.items.length) subs.push(sub);
return subs;
}, []);
if (cat.subCategories.length) cats.push(cat);
return cats;
}, []);
console.log(result);
Here I have a working example which returns your requested output:
function finder(data, query) {
for(let i in data) {
// return the item if the label contains the search query
if(new RegExp(query,"i").test(data[i].label)) return data[i]
// go deeper in subCategories if exist
if(data[i].subCategories) {
let sub = finder(data[i].subCategories, query)
if(sub) {
data[i].subCategories = [sub]
return data[i]
}
// go deeper in items if exist
} else if(data[i].items){
let item = finder(data[i].items, query)
if(item) {
data[i].items = [item]
return data[i]
}
}
}
// didn't find the search query in this branch
return false
}
console.log(finder(data, 'Greek'))
with data your input data
As the question states, I want to create a new object from a current json object.
My current json object:
{
"name": "Parent",
"children": [
{
"name": "Child1",
"children": [
{
"name": "GrandChid1",
"children": []
},
{
"name": "GrandChild2",
"children": []
},
{
"name": "GrandChild3",
"children": [
{
"name": "GrandGrandChild1",
"children": [
{
"name": "GrandGrandGrandChild1",
"children": []
},
{
"name": "GrandGrandGrandChild2",
"children": []
}
]
}
]
}
]
}
]
}
Now the new object will look something like this:
{
"Parent": [
{
"Child1": [
{
"GrandChid1": ''
},
{
"GrandChild2": ''
},
{
"GrandChild3": [
{
"GrandGrandChild1": [
{
"GrandGrandGrandChild1": ''
},
{
"GrandGrandGrandChild2": ''
}
]
}
]
}
]
}
]
}
If there are no children then it becomes a string (simple key value) pair.
Any help is appreciated especially with a recursive solution.
Try
let r = o=> (o.children=o.children.map(x=>r(x)),
{[o.name]: o.children.length ? o.children:''});
let c= {
"name": "Parent",
"children": [
{
"name": "Child1",
"children": [
{
"name": "GrandChid1",
"children": []
},
{
"name": "GrandChild2",
"children": []
},
{
"name": "GrandChild3",
"children": [
{
"name": "GrandGrandChild1",
"children": [
{
"name": "GrandGrandGrandChild1",
"children": []
},
{
"name": "GrandGrandGrandChild2",
"children": []
}
]
}
]
}
]
}
]
}
let r = o=> (o.children=o.children.map(x=>r(x)),{[o.name]: o.children.length ? o.children:''});
console.log(r(c));
This question already has answers here:
Find by key deep in a nested array
(21 answers)
Closed 4 years ago.
I have a Javascript object with lots of different sections. How can I search through all of the sections to find the position of a specific ID? The ID's that I am searching for are not in a specific location, and can be located in any of the tree branches.
For example, I am searching for this ID:
xobmnbjxg0g_1527269346261
And I am trying to output the position of that ID, which would be this:
app['structure'][0]['if-children'][0]['id']
My Javascript Object:
var app = {
"structure": [
{
"id": "0",
"type":"IF",
"parameters": [
{
"id": "xobmnbjxg0g_1527269346260",
"type": "field",
"value": "CV_TEST_SPOT1X"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children": [
{
"id": "xobmnbjxg0g_1527269346261",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children":[
],
"else-children":[
]
}
],
"else-children":[
{
"id": "xobmnbjxg0g_1527269346262",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
},
{
"id": "2",
"type": "operator",
"value": "="
},
{
"id": "3",
"type": "field",
"value": "North America"
}
],
"if-children":[
{
"id":"xobmnbjxg0g_152726934626X"
}
],
"else-children":[
{
"id":"xobmnbjxg0g_152726934626Y"
}
]
}
]
},
{
"id": "xobmnbjxg0g_1527269346263",
"type":"IF",
"parameters": [
[
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
]
],
"if-children": [
{
"id": "xobmnbjxg0g_1527269346264",
"type":"IF",
"parameters": [
[
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
]
],
"if-children":[
{
"id": "xobmnbjxg0g_1527269346265",
"type":"IF",
"parameters": [
{
"id": "1",
"type": "field",
"value": "CV_TEST_SPOT1"
}
],
"if-children":[
{
"id":"xobmnbjxg0g_1527269346266"
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346267"
}
]
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346268"
}
]
}
],
"else-children":[
{
"id":"xobmnbjxg0g_1527269346269"
}
]
}
]
};
Interesting puzzle/question.
pretty sure there are some edge cases im missing but this seems to pass some tests.
function is(obj, type){
return Object.prototype.toString.call(obj) === `[object ${type}]`;
}
function findPosition(obj, mykey, myval, res){
if(is(obj, "Object")){
if(mykey in obj && obj[mykey] === myval){
res.tree.push(mykey);
res.found = true;
} else {
for( let key in obj){
if(res.found) break;
res.tree.push(key);
findPosition(obj[key], mykey, myval, res);
}
if(!res.found) res.tree.pop();
}
} else if(is(obj, "Array")){
for(let i = 0; i < obj.length; i++){
if(res.found) break;
res.tree.push(i);
findPosition(obj[i], mykey, myval, res);
}
if(!res.found) res.tree.pop();
} else {
res.tree.pop();
}
return res;
}
Usage and output
findPosition([{one: { two: [{id: [{id:'my'}]}]}}], "id", "mys", {tree:[], found: false})
> tree: Array(0), found: false}
findPosition([{one: { two: [{id: [{id:'my'}]}]}}], "id", "my", {tree:[], found: false})
> {found: true, tree: [0, "one", "two", 0, "id", 0, "id"]}
For finding if current obj you are iterating over is an Array you can also use Array.isArray