Home > front end >  Javascript JSON transform using Map, Reduce, Aggregate
Javascript JSON transform using Map, Reduce, Aggregate

Time:02-12

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 Screenshot of JSON to TS

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

  • Related