I am beating my head trying to figure out this transformation.
This is the format of the JSON
I have:
{
"itineraryId": "063fc878-b118-49fc-9106-39d51f647c9e",
"reservations": [
{
"confirmNumber": "54047SC008976",
"startDate": "2021-11-20T00:00:00.000Z"
},
{
"confirmNumber": "54047SC008975",
"startDate": "2021-11-13T00:00:00.000Z"
},
{
"confirmNumber": "54058SC007379",
"startDate": "2021-08-13T00:00:00.000Z"
}
]
}
I need:
[{
"itineraryId": "063fc878-b118-49fc-9106-39d51f647c9e",
"month": "November 2021",
"reservations": [{
"confirmNumber": "54047SC008976",
"startDate": "2021-11-20T00:00:00.000Z"
},
{
"confirmNumber": "54047SC008975",
"startDate": "2021-11-13T00:00:00.000Z"
}
]
}, {
"itineraryId": "063fc878-b118-49fc-9106-39d51f647c9e",
"month": "August 2021",
"reservations": [{
"confirmNumber": "54058SC007379",
"startDate": "2021-08-13T00:00:00.000Z"
}]
}]
I need it that way so that I can build a
CodePudding user response:
I've often wished for some kind of easy "group by" function in JavaScript, but you can achieve the same effect with reduce()
. Essentially, you can build up an array of grouped results by either creating or updating a group depending on if it already exists during each call to the reducer function:
const monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
const initial = {
"itineraryId": "063fc878-b118-49fc-9106-39d51f647c9e",
"reservations": [{
"confirmNumber": "54047SC008976",
"startDate": "2021-11-20T00:00:00.000Z"
},
{
"confirmNumber": "54047SC008975",
"startDate": "2021-11-13T00:00:00.000Z"
},
{
"confirmNumber": "54058SC007379",
"startDate": "2021-08-13T00:00:00.000Z"
}
]
};
const groupedReservations = initial.reservations.reduce((reservationGroups, reservation) => {
// Calculate the key that uniquely identifies the group, then look it up
const date = new Date(reservation.startDate);
const reservationMonth = monthNames[date.getMonth()] " " date.getFullYear();
const existingGroup = reservationGroups.find(group => group.month === reservationMonth);
// If the group doesn't exist, create it - otherwise, add the reservation to it
if (!existingGroup) {
reservationGroups.push({
itineraryId: initial.itineraryId,
month: reservationMonth,
reservations: [reservation]
});
} else {
existingGroup.reservations.push(reservation);
}
return reservationGroups;
}, []);
console.log(groupedReservations);
Note that I basically treat itineraryId
as an afterthought here, since denormalizing the data didn't seem like an important step. Let me know if the context of your code requires something different.
CodePudding user response:
Here minified implementation
const { DateTime } = require("luxon");
// Convert ISO date to human readable date : August 2021
const formatYearMonth = (dateISO) => {
const parsedDate = DateTime.fromISO(dateISO);
const year = parsedDate.toFormat("yyyy");
const month = parsedDate.toFormat("LLLL");
return `${month} ${year}`;
};
const getItineraryMonths = (reservations) => {
let months = {};
reservations.forEach((reservation) => {
const formattedMonth = formatYearMonth(reservation.startDate);
months[formattedMonth] = formattedMonth;
});
return Object.keys(months);
};
// Get reservation in specified month for specific itinerary
const getReservationsInMonth = (reservations, formatedMonthIn) => {
return reservations.filter((reservation) => {
const formattedMonth = formatYearMonth(reservation.startDate);
return formattedMonth === formatedMonthIn;
});
};
// Reformat JSON response
const formatJsonResponse = (response) => {
const itineraryMonths = getItineraryMonths(response.reservations);
const formattedResult = itineraryMonths.map((month) => {
return {
itineraryId: response.itineraryId,
month,
reservations: getReservationsInMonth(response.reservations, month),
};
});
return formattedResult;
};
console.log(formatJsonResponse(input));
Test solution - https://replit.com/@EmmanuelBYIRING/json-sanitise#index.js