My application is MVC 5, I am using the following Ajax to generate an array:
$.ajax({
type: "Post",
url: '@Url.Action("Getthereport", "Surveys")',
async: false,
cache: false,
dataType: "json",
data: { 'test': "All" },
success: function (result) {
if (result && result.Grid.length > 0) {
for (let i = 0; i < result.Grid.length; i++) {
jsonData.push({
Question: result.Grid[i].Body,
QuestionId: result.Grid[i].QuestionId,
myData: { name: result.Grid[i].name, value: result.Grid[i].value }
});
};
}
},
complete: function () {
reduce();
},
error: function(err) {
alert(err.status + " : " + err.statusText);
}
});
I generates the following:
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{ name: 'No', value: 1 }] },
{
Question: "Was the training useful?",
QuestionId: 1 ,
myData: [{ name: 'Yes', value: 1 }]
}];
to merge the objects, I use:
const result = Object.values(jsonData.reduce((acc, obj) => {
if (!acc[obj.QuestionId]) {
acc[obj.QuestionId] = obj;
} else {
acc[obj.QuestionId].myData = acc[obj.QuestionId].myData.concat(obj.myData);
}
return acc;
Works great if the array is hardcoded and generates:
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: [{ name: 'No', value: 1 },
{ name: 'Yes', value: 1 }]
}];
However, if the array is generated by Ajax call, I get the following error:
acc[obj.QuestionId].myData.concat is not a function
I tried to run the reduce script on Ajax complete and directly both did not work.
In the success property of your ajax call options you're pushing myData as an object, not as an array
success: function (result) {
if (result && result.Grid.length > 0) {
for (let i = 0; i < result.Grid.length; i++) {
jsonData.push({
Question: result.Grid[i].Body,
QuestionId: result.Grid[i].QuestionId,
myData: { name: result.Grid[i].name, value: result.Grid[i].value }
});
};
}
},
Which means that the output is not as you stated but rather
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: { name: 'No', value: 1 } //<-- Objects not arrays
},
{
Question: "Was the training useful?",
QuestionId: 1,
myData: { name: 'Yes', value: 1 }
}
];
You can either declare it as an array at that stage to generate the output you originally posted,
for (let i = 0; i < result.Grid.length; i++) {
jsonData.push({
...
myData: [{ name: result.Grid[i].name, value: result.Grid[i].value }]
});
};
or adjust your reduce.
var jsonData = [
{
Question: "Was the training useful?",
QuestionId: 1,
myData: { name: 'No', value: 1 }
},
{
Question: "Was the training useful?",
QuestionId: 1,
myData: { name: 'Yes', value: 1 }
}
];
const result = Object.values(jsonData.reduce((acc, obj) => {
acc[obj.QuestionId] ??= { ...obj, myData: [] };
acc[obj.QuestionId].myData.push(obj.myData);
return acc;
}, {}));
console.log(JSON.stringify(result, null, 2))