Replace path name to get value using received JSON response key javascript - javascript

Given json response below.
{
"status": "success",
"data": {
"cheapest": {
"data": [
{
"logistic_id": 1,
"rate_id": 21
}
]
},
"reguler": {
"data":[
{
"logistic_id": 5,
"rate_id": 74
}
]
},
"ranked": {
"data": []
}
}
}
to get logistic_id value and store to logisticIdValue, I use path:
set("logisticIdValue", x.data.reguler.data[0].logistic_id)
I want to get logistic_id value from response using iteration so i don't have to write const cheapest, reguler and ranked to iterate. It might involve key syntax, something like this but i don't know whats the proper syntax to do this
set("logisticIdValue", x.data.key[1].data[0].logistic_id)

let data = {
"status": "success",
"data": {
"cheapest": {
"data": [{
"logistic_id": 1,
"rate_id": 21
}]
},
"reguler": {
"data": [{
"logistic_id": 5,
"rate_id": 74
}]
},
"ranked": {
"data": []
}
}
};
for (const [key, value] of Object.entries(data)) {
if (key === 'data') {
for (const [key1, value1] of Object.entries(value)) {
for (const [key2, value2] of Object.entries(value1)) {
value2 && value2.map((e, i, arr) => {
console.log('logistic_id:', e.logistic_id);
})
}
}
}
}

In case you need to get array of logistic_id values for all types (cheapest,reguler, ..)
so you can use reduce function to iterate on Object.Keys and accumulate it into array as the following:
const data = {
"status": "success",
"data": {
"cheapest": {
"data": [
{
"logistic_id": 1,
"rate_id": 21
}
]
},
"reguler": {
"data": [
{
"logistic_id": 5,
"rate_id": 74
}
]
},
"ranked": {
"data": []
}
}
};
const logisticIdValues = Object.keys(data.data).reduce((result, key) => {
if (data.data[key].data.length > 0) {
result.push(data.data[key].data[0].logistic_id);
}
return result;
}, []);
console.log(logisticIdValues)
but if you need to get it attached to its type so you can accumulated it in hash instead of array as the following:
const data = {
"status": "success",
"data": {
"cheapest": {
"data": [
{
"logistic_id": 1,
"rate_id": 21
}
]
},
"reguler": {
"data": [
{
"logistic_id": 5,
"rate_id": 74
}
]
},
"ranked": {
"data": []
}
}
};
const logisticIdValuesObj = Object.keys(data.data).reduce((result, key) => {
if (data.data[key].data.length > 0) {
result[key] = data.data[key].data[0].logistic_id;
}
return result;
}, {});
console.log(logisticIdValuesObj)

Related

Converting one json object to another with jquery

i have an input json object , and i want the below output json from a jquery function . How can i achieve it with min lines of code .
Input
{
"dashboardWidgetFacility": [{
"deskUsageInput": {
"breakup": [{
"location_breakup_0": ["{\"id\":1,\"name\":\"campus\"},{\"id\":8,\"name\":\"building \"}"],
"teams_breakup_0": ["3", "6"]
}, {
"location_breakup_1": ["{\"id\":1,\"name\":\"campus\"},{\"id\":8,\"name\":\"building \"},{\"id\":83,\"name\":\"floor \"}"],
"teams_breakup_1": ["3", "2"]
}]
}
}]
}
Output Object
{
"dashboardWidgetFacility": [{
"campus": {
"id": 1
},
"building": {
"id": 8
},
"widgetInput": {
"deskUsageInput": {
"teams": ["3", "6"]
}
}
}, {
"campus": {
"id": 1
},
"building": {
"id": 8
},
"floor": {
"id": 83
},
"widgetInput": {
"deskUsageInput": {
"teams": ["3", "2"]
}
}
}]
}
Here location breakup location_breakup_{index} , has the index.
I had to correct those location_breakup values because you have to parse out the json, but theyre not technically valid json on their own since theyre missing the square brackets on the sides.
const input = {
dashboardWidgetFacility: [
{
deskUsageInput: {
breakup: [
{
location_breakup_0: [
'{"id":1,"name":"campus"},{"id":8,"name":"building "}',
],
teams_breakup_0: ['3', '6'],
},
{
location_breakup_1: [
'{"id":1,"name":"campus"},{"id":8,"name":"building "},{"id":83,"name":"floor "}',
],
teams_breakup_1: ['3', '2'],
},
],
},
},
],
};
const output = Object.values(
input.dashboardWidgetFacility[0].deskUsageInput.breakup
).reduce(
(acc, item) => {
const nestedItem = Object.keys(item).reduce((acc, key) => {
let locationParsed;
let teamsBreakup;
if (key.startsWith('location_breakup')) {
locationParsed = JSON.parse('[' + item[key] + ']');
}
if (key.startsWith('teams_breakup')) {
teamsBreakup = item[key];
}
const obj = (locationParsed || []).reduce(
(acc, item) => {
const { name, id } = item;
return {
...acc,
[name.trim()]: {
id,
},
};
},
{
widgetInput: {
deskUsageInput: {
teams: null,
},
},
}
);
obj.widgetInput.deskUsageInput.teams = teamsBreakup;
return {
...acc,
...obj,
};
}, {});
return {
dashboardWidgetFacility: [...acc.dashboardWidgetFacility, nestedItem],
};
},
{
dashboardWidgetFacility: [],
}
);
console.log(output);

how to get max value from a nested json array

I have a nested json array and I am trying to get the maximum value of the points attribute in this array.
data = {
"name": "KSE100",
"children": [
{
"name": "TECHNOLOGY & COMMUNICATION",
"children": [
{
"name": "TRG",
'points': -21
},
{
"name": "SYS",
},
]
},
{
"name": "OIL",
"children": [
{
"name": "PPL",
'points': 9
},
{
"name": "PSO",
'points': -19
},
]
},
]
}
I want the max value of points from under the children sections. I mean from under technology and oil sectors.
What I've done so far:
var max;
for (var i in data.children.length) {
for (var j in data.data[i]) {
var point = data.data[i].children[j]
}
}
Try the following:
data = {
"name": "KSE100",
"children": [
{
"name": "TECHNOLOGY & COMMUNICATION",
"children": [
{
"name": "TRG",
'points': -21
},
{
"name": "SYS",
},
]
},
{
"name": "OIL",
"children": [
{
"name": "PPL",
'points': 9
},
{
"name": "PSO",
'points': -19
},
]
},
]
}
var array = [];
for (var first of data.children) {
for (var second of first.children) {
if(second.points != undefined)
{
array.push(second);
}
}
}
var maximumValue = Math.max.apply(Math, array.map(function(obj) { return obj.points; }));
console.log(maximumValue);
you can use the reduce method on the array object to do this
const maxValues = []
data.children.forEach(el => {
if (el.name === 'OIL' || el.name === 'TECHNOLOGY & COMMUNICATIO'){
const max = el.children.reduce((current, previous) => {
if (current.points > previous.points) {
return current
}
}, 0)
maxValues.append({name: el.name, value: max.points})
}
})
This will give you an array of the objects with the name and max value.
First you can convert your object to a string through JSON.stringify so that you're able to use a regular expression
(?<=\"points\":)-?\\d*
To matchAll the values preceded by the pattern \"points\": that are or not negative values. After it, convert the result to a array through the spread operator ... and then reduce it to get the max value.
const data = {name:"KSE100",children:[{name:"TECHNOLOGY & COMMUNICATION",children:[{name:"TRG",points:-21},{name:"SYS"}]},{name:"OIL",children:[{name:"PPL",points:9},{name:"PSO",points:-19}]}]};
console.log(
[ ...JSON.stringify(data).matchAll('(?<=\"points\":)-?\\d*')]
.reduce((acc, curr) => Math.max(curr, acc))
)
I wasn't 100% sure, what your exact goal is, so I included a grouped max value and and overall max value with a slight functional approach.
Please be aware that some functionalities are not working in older browsers i.e. flatMap. This should anyways help you get started and move on.
const data = {
name: "KSE100",
children: [
{
name: "TECHNOLOGY & COMMUNICATION",
children: [
{
name: "TRG",
points: -21,
},
{
name: "SYS",
},
],
},
{
name: "OIL",
children: [
{
name: "PPL",
points: 9,
},
{
name: "PSO",
points: -19,
},
],
},
],
};
const maxPointsByGroup = data.children.reduce(
(acc, entry) => [
...acc,
{
name: entry.name,
max: Math.max(
...entry.children
.map((entry) => entry.points)
.filter((entry) => typeof entry === "number")
),
},
],
[]
);
console.log("grouped max:", maxPointsByGroup);
const overallMax = Math.max(
...data.children
.flatMap((entry) => entry.children.flatMap((entry) => entry.points))
.filter((entry) => typeof entry === "number")
);
console.log("overall max:", overallMax);

Parent and Child array sorting doesn't working accordingly

I have list of tree node metadataList Like below:
[
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
}
]
},
{
"data": {
"metadata": {
"category": [
"Isv"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Isv"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Isv"
]
}
},
"children": [
]
}
]
},
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
}
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Isv"
]
}
},
"children": [
]
}
]
},
{
"data": {
"metadata": {
"category": [
"Incentives"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Incentives"
]
}
},
"children": [
]
}
]
}
]
Which is a type of array of data and children collection it's class like below:
export default class CurrentTopicMetadataTreeNode {
public data: CurrentTopicMetadata;
public children: CurrentTopicMetadataTreeNode[];
}
export default class CurrentTopicMetadata {
public id: string;
public metadata: TopicMetadata
}
export class TopicMetadata {
public category: Category[]
}
export enum Category {
Csp = 'Csp',
Mpn = 'Mpn',
Incentives = 'Incentives',
Referrals = 'Referrals',
Isv = 'Isv',
}
What I am trying, to filter list as data and children order as per category. Let say if filter by a category all data and children belongs to that category should come like below order.
But I am getting data like this order :
One Element On Array Problem Set:
Here in this array if I search with Csp Only data in root node which is Csp and data in children only has one data which contains Csp would be in array.
[{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
},
{
"data": {
"metadata": {
"category": [
"Mpn"
]
}
},
"children": [
]
}
]
}]
Expected Output: So after filtered by Csp node should be look like this:
[
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
{
"data": {
"metadata": {
"category": [
"Csp"
]
}
},
"children": [
]
}
]
}
]
here is my code, where I am doing wrong?
// Rule 1 check parent metadata category whether be empty
// Rule 2 and 3
function find_in_children(children, parent_category) {
children_has_same_category = []
for(var i in children) {
let child = children[i];
if(child.children != undefined && child.children.length > 0 && child.data.metadata.category == parent_category) {
children_has_same_category.push(child);
}
}
if(children_has_same_category.length > 0) {
return children_has_same_category
} else {
for(var i in children) {
let child = children[i];
return find_in_children(child.children, parent_category);
}
}
}
function check_object(object) {
let parent_category = object.data.metadata.category[0];
if(object.children != undefined && object.children.length > 0) {
return {'data': object.data, 'children': find_in_children(object.children, parent_category)}
} else {
return {'data': object.data}
}
}
function apply_rules(object) {
// Rule 1 check parent metadata category whether be empty
if(object.data.metadata.category.length > 0) {
return {'data': object.data}
} else {
return check_object(object)
}
}
target = {
value: 'Isv'
}
filtered_datas = []
for(var i in datas) {
let data = datas[i];
if(data.data.metadata.category.length > 0) {
result = apply_rules(data)
if(result.data.metadata.category[0] == target.value) {
filtered_datas.push(result);
}
}
}
Here is the data sample and result: https://jsfiddle.net/faridkiron/b02cksL8/#&togetherjs=F7FK3fBULx
Another Recursive Function I have tried:
handleRecursiveParentChildNode(parent: CurrentTopicMetadataTreeNode, searchKey) {
let result = parent;
result.children = [];
if (parent.children.length > 0) {
parent.children.forEach(child => {
let childData = this.handleRecursiveParentChildNode(child, searchKey);
if (childData.data && childData.data != undefined)
result.children.push(childData);
});
let cate = parent.data.metadata.category.filter(cat => cat === searchKey);
if (!result.children && cate.length < 1) {
result = null;
}
}
else {
let cate = parent.data.metadata.category.filter(cat => cat === searchKey);
if (cate.length < 1) {
result = null;
}
}
return result;
}
You can filter the data with Array.prototype.filter
const data = [{"data":{"metadata":{"category":["Csp"]}},"children":[{"data":{"metadata":{"category":["Csp"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]}]},{"data":{"metadata":{"category":["Isv"]}},"children":[{"data":{"metadata":{"category":["Isv"]}},"children":[]},{"data":{"metadata":{"category":["Isv"]}},"children":[]}]},{"data":{"metadata":{"category":["Csp"]}},"children":[{"data":{"metadata":{"category":["Csp"]}},"children":[]}]},{"data":{"metadata":{"category":["Mpn"]}},"children":[{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Csp"]}},"children":[]},{"data":{"metadata":{"category":["Isv"]}},"children":[]}]},{"data":{"metadata":{"category":["Incentives"]}},"children":[{"data":{"metadata":{"category":["Incentives"]}},"children":[]}]}]
const dfs = (iNode, type) => {
const node = Object.assign({}, iNode) // shallow copy current node
node.children = iNode.children.flatMap(child => {
// if child matches type, return it, otherwise filter it out
return child.data.metadata.category.includes(type) ? dfs(child, type) : []
})
return node
}
// fakes a root node to apply dfs on
const cspList = dfs({ children: data }, 'Csp').children
console.log(JSON.stringify(cspList, null, 2))
edit: in case flatMap can't be used (for some reasons) it is possible to use filter + map
const data = [{"data":{"metadata":{"category":["Csp"]}},"children":[{"data":{"metadata":{"category":["Csp"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]}]},{"data":{"metadata":{"category":["Isv"]}},"children":[{"data":{"metadata":{"category":["Isv"]}},"children":[]},{"data":{"metadata":{"category":["Isv"]}},"children":[]}]},{"data":{"metadata":{"category":["Csp"]}},"children":[{"data":{"metadata":{"category":["Csp"]}},"children":[]}]},{"data":{"metadata":{"category":["Mpn"]}},"children":[{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Mpn"]}},"children":[]},{"data":{"metadata":{"category":["Csp"]}},"children":[]},{"data":{"metadata":{"category":["Isv"]}},"children":[]}]},{"data":{"metadata":{"category":["Incentives"]}},"children":[{"data":{"metadata":{"category":["Incentives"]}},"children":[]}]}]
const dfs = (iNode, type) => {
const node = Object.assign({}, iNode) // shallow copy current node
node.children = iNode.children
.filter(child => child.data.metadata.category.includes(type))
.map(child => dfs(child, type))
return node
}
// fakes a root node to apply dfs on
const cspList = dfs({ children: data }, 'Csp').children
console.log(JSON.stringify(cspList, null, 2))
regarding errors in original code
handleRecursiveParentChildNode(parent: CurrentTopicMetadataTreeNode, searchKey) {
let result = parent;
result.children = [];
// bug? since we are called from parent we obviously are a children
// so else block is never run
if (parent.children.length > 0) {
parent.children.forEach(child => {
let childData = this.handleRecursiveParentChildNode(child, searchKey);
// bug ? we never filter out children and push every one of them on result
if (childData.data && childData.data != undefined)
result.children.push(childData);
});
// bug ? !result.children is never truthy (![] === false)
// so if is never run
let cate = parent.data.metadata.category.filter(cat => cat === searchKey);
if (!result.children && cate.length < 1) {
result = null;
}
}
// never run
else {
let cate = parent.data.metadata.category.filter(cat => cat === searchKey);
if (cate.length < 1) {
result = null;
}
}
return result;
}
You can use recursive call reduce for filter your data:
const filterItems = (items, f) => {
const fitems = items.reduce((acc, rec) => {
const children = rec.children.length > 0 ? filterItems(rec.children, f): []
if (rec.data.metadata.category.indexOf(f) >= 0) {
return [...acc, {...rec, children}]
}
return [...acc]
}, [])
return fitems
}

How to Iterate the array of array in javascript?

Json:( How to iterate this array of arrays using map function.. I have tried this.. In this.materialList => array i am getting only 1 st array of values 2nd and 3rd array values are getting undefined.. so i am not able to display in html.. )
subrecipes:[
subrecipematerials: [
"id": 1
"material_id": {
"id":1,
"title":"cookies"
}
],
[
"id": 2
material_id: {
"id":2,
"title":"cake"
}
]
subrecipeformulations: [
"id": 1,
"formula_id": {
"id":1,
"title":formula1
}
]
]
subrecipes:[
subrecipematerials: [
"id": 1
material_id: {
"id":1,
"title":"cookies"
}
],
[
"id": 2
material_id: {
"id":2,
"title":"cake"
}
]
subrecipeformulations: [
"id": 1,
"formula_id": {
"id":1,
"title":formula1
}
]
]
component.ts(I have tried this.. In this.materialList => array i am getting only 1 st array of values 2nd and 3rd array values are getting undefined.. so i am not able to display in html.. )
let subrecipeMaterials = this.data.subRecipes.map((item, index) => {
item = item.subrecipeMaterials[index]
return item
})
let tempMatList1 = this.group_By_Data(subrecipeMaterials, "sub_recipe_id")
let matSubrecipies = Object.keys(tempMatList1).map(data => tempMatList1[data])
this.filterMaterials(matSubrecipies)
this.subrecipies = matSubrecipies.map((data, index) => {
return {
matList: this.materialList[index],
formList: this.otherFormulationList[index],
subRec: (index + 1)
}
})
group_By_Data(arr, key) {
return arr.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
}
filterMaterials(matSubrecipies) {
this.materialList = matSubrecipies.map(sub => {
return sub.filter(mat => {
let checkmat_id = mat.material_id
if (!!checkmat_id) }
return mat.material_id
}
})
})
}
getMaterialListArray(i) {// this function used to display this array through html.. right now only i am getting 1st array..
return this.materialList[i]
}
Your data is not correct. I think it should be in the form:
{subrecipes:[{
subrecipematerials: [{
"id": 1,
"material_id": {
"id":1,
"title":"cookies"
},
},
{
"id": 2,
material_id: {
"id":2,
"title":"cake"
}
}],
subrecipeformulations: [{
"id": 1,
"formula_id": {
"id":1,
"title":"formula1"
}
}]
},
{
subrecipematerials: [{
"id": 1,
material_id: {
"id":1,
"title":"cookies"
}
},
{
"id": 2,
material_id: {
"id":2,
"title":"cake"
}
} ] ,
subrecipeformulations: [{
"id": 1,
"formula_id": {
"id":1,
"title":"formula1"
}
}]
}]
};
Also, the code item = item.subrecipeMaterials[index] should be item = item.subrecipematerials[index] (difference is M and m as it is case sensitive).

modify json object and save it

I do have a json array object. I need to modify it then save the modified version on a variable.
the json object
var json = [
{
"Name": "March-2016",
"Elements": [
{
"Name": "aa",
"Elements": [
{
"Name": "ss",
"Data": {
"Test1": [
22
],
"Test2": [
33
],
"Test3": [
44
],
"Test4": [
55
]
}
},
{
"Name": "ssee",
"Data": {
"Test12": [
222
],
"Test22": [
3322
],
"Test32": [
445
],
"Test42": [
553
]
}
}
]
}
]
}
];
need to be modified to
var json = [
{
"Name": "March-2016",
"Elements": [
{
"Name": "aa",
"Elements": [
{
"category": "ss",
"Test1": 22,
"Test2": 33 ,
"Test3":44,
"Test4": 55
},
{
"category": "ssee",
"Test12": 222,
"Test22": 3322 ,
"Test32":445,
"Test42": 553
}
]
}
]
}
];
I have this method but its not doing the job
var saveJson = function(arr) {
var nameValuePairs = [];
for (var i = 0, len = arr.length; i < len; i++) {
var item = arr[i];
if (item.Data) {
var newvar = {
category : item.Name
}
newvar[Object.keys(item.Data)] = Object.values(item.Data);
item = newvar
}
if (item.Elements) {
nameValuePairs = nameValuePairs.concat(saveJson(item.Elements));
}
}
return arr;
};
I need this conversion to be dynamic as for sure I will get bigger json than the posted one
sorry for the confusion and thanks in advance.
The original object is really a mess, but still you just need to step through it and pull out the values you want. This changes the json object in place:
json.forEach(item => {
item.Elements.forEach(Outer_El => {
Outer_El.Elements = Outer_El.Elements.map(item =>{
let obj = {category: item.Name}
Object.keys(item.Data).forEach(key => {
obj[key] = item.Data[key][0]
})
return obj
})
})
})
json should now look like:
[{
"Name":"March-2016",
"Elements":[
{
"Name":"aa",
"Elements":[
{
"category":"ss",
"Test1":22,
"Test2":33,
"Test3":44,
"Test4":55
},
{
"category":"ssee",
"Test1e":224,
"Test2e":334,
"Test3e":443,
"Test4e":554
}
]
}
]
}]
You can use destructuring assignment to get specific property values from an object
{
let {Name:categories, Data:{Test:[Test]}} = json[0].Elements[0].Elements[0];
json[0].Elements[0].Elements[0] = {categories, Test};
}

Categories

Resources