Organize the JSON data in a particular manner

I have a set of JSON data that looks like this:

[
  {
    "name": "Event 1",
    "sponsors": [
      {
        "name": "Walmart",
        "location": "Seattle"
      },
      {
        "name": "Target",
        "location": "Portland"
      },
      {
        "name": "Amazon",
        "location": "San Francisco"
      }
    ]
  },
  {
    "name": "Event 2",
    "sponsors": [
      {
        "name": "Google",
        "location": "Los Angeles"
      },
      {
        "name": "Apple",
        "location": "Cupertino"
      },
      {
        "name": "Microsoft",
        "location": "Redmond"
      }
    ]
  },
  {
    "name": "Event 3",
    "sponsors": [
      {
        "name": "Facebook",
        "location": "Menlo Park"
      },
      {
        "name": "Twitter",
        "location": "San Francisco"
      },
      {
        "name": "LinkedIn",
        "location": "Sunnyvale"
      }
    ]
  }
]

Now, I want to showcase this JSON data on a webpage in a specific format:

Location X
   Sponsor X
      Event 1
      Event 2
      -------
   Sponsor Y
      Event 1
Location Y
   Sponsor Y
      Event 1
      Event 2
      ------
   --------

Essentially, I need to flip the structure of the JSON dataset to display Locations at the top level and other elements as children under them. I attempted to use VueJS computed properties for looping through the JSON file but haven't succeeded yet. Can someone guide me on how I can achieve this?

I apologize if my terminology is not accurate; I'm unsure what this type of display is called technically.

Answer №1

If you're looking for a simple solution, consider following these steps:

  • Firstly, pass your JSON data to Vue within the data object.

  • Next, create a computed property called 'formattedData' and define a function that formats the JSON data in the desired way.

  • Finally, utilize this computed property in the template to display the formatted data.

Here is a rough guide on how you can achieve this:

var concertData = [
    {
        "name": "Concert 1",
        "sponsors": [
            {
                "name": "Woolworths",
                "location": "Mildura"
            },
            {
                "name": "Coles",
                "location": "Melbourne"
            },
            {
                "name": "Metricon",
                "location": "Wagga Wagga"
            }
        ]
    },
    // Additional concert data here
];

new Vue({
  data: {
    concerts: concertData // Include your concert JSON here
  },
    computed: {
        formattedData: function () {
            var formattedData = new Map();
            this.concerts.forEach(function (item) {
                item.sponsors.forEach(function (sponsor) {
                    if (!formattedData.has(sponsor.location)) {
                        formattedData.set(sponsor.location, new Map());
                    }

                    if (!formattedData.get(sponsor.location).has(sponsor.name)) {
                        formattedData.get(sponsor.location).set(sponsor.name, []);
                    }

                    formattedData.get(sponsor.location).get(sponsor.name).push(item.name);
                })
            });

            return formattedData;
        }
    },
    render: function(h) {
        // Use this.formattedData to render the display
    }

}).$mount("#app");

Answer №2

Here is a guide on how to transform the data:

const info = [{
    "title": "Event 1",
    "sponsors": [
      {"name": "Woolworths","location": "Melbourne"},
      {"name": "Coles","location": "Melbourne"},
      {"name": "Metricon","location": "Wagga Wagga"}
    ]
  },
  {
    "title": "Event 2",
    "sponsors": [
      {"name": "Metricon","location": "Albert Park"},
      {"name": "Woolworths","location": "Melbourne"},
      {"name": "ALDI","location": "Bendigo"}
    ]
  },
  {
    "title": "Event 3",
    "sponsors": [
      {"name": "Holcim","location": "Bendigo"},
      {"name": "Westpac","location": "Melbourne"},
      {"name": "Coles","location": "Mildura"}
    ]
  }
];

const byLocation = info.reduce((result, event) => (event.sponsors.forEach(sponsor => {
  if (!result[sponsor.location]) result[sponsor.location] = {};
  if (!result[sponsor.location][sponsor.name]) result[sponsor.location][sponsor.name] = [];
  result[sponsor.location][sponsor.name].push(event.title);
}), result), {});

console.log(byLocation);

To clarify the above:

To convert the initial info Array of events

[
  event,
  event,
  // ...
]

into an Object - where all the property names (locations) are distinct

{
  "location name 1": {},
  "location name 2": {},
  // ...
}

the first approach would be to utilize Array.prototype.reduce() MDN:

const byLocation = info.reduce((finalObject, event) => {
  // Add event details into finalObject here
  return finalObject; // Return the new Object for the next iteration
}, {}); // << {} represents the finalObject

a bit of renaming and using Arrow function's Implicit Return we can simplify the above as follows:

const byLocation = info.reduce((r, e) => (/*Insert e details into r*/, r), {});

Therefore, e signifies the current Event being processed, and r is the Resulting object we need to construct.
Let's fill up the r object by looping through the e.sponsors Array

  e.sponsors.forEach(sp => { // sp is the active Sponsor
    // If r["location name"] doesn't exist, create an empty object for it
    if (!r[sp.location]) r[sp.location] = {};
    // If r["location name"]["Sponsor name"] doesn't exist, create it
    // as an empty array
    if (!r[sp.location][sp.name]) r[sp.location][sp.name] = [];
    // Finally, add the Event title into that array.
    r[sp.location][sp.name].push(e.title);
  })

If the concept seems too complex, another way to write it could look like this:

const info = [{
    "title": "Event 1",
    "sponsors": [
      {"name": "Woolworths","location": "Melbourne"},
      {"name": "Coles","location": "Melbourne"},
      {"name": "Metricon","location": "Wagga Wagga"}
    ]
  },
  {
    "title": "Event 2",
    "sponsors": [
      {"name": "Metricon","location": "Albert Park"},
      {"name": "Woolworths","location": "Melbourne"},
      {"name": "ALDI","location": "Bendigo"}
    ]
  },
  {
    "title": "Event 3",
    "sponsors": [
      {"name": "Holcim","location": "Bendigo"},
      {"name": "Westpac","location": "Melbourne"},
      {"name": "Coles","location": "Mildura"}
    ]
  }
];

const byLocation = {}; // The resulting object with unique Locations

info.forEach((event) => {

  const sponsors = event.sponsors;
  
  sponsors.forEach((sponsor) => {
  
    if (!byLocation.hasOwnProperty(sponsor.location)) {
        byLocation[sponsor.location] = {};
    }
    
    if (!byLocation[sponsor.location].hasOwnProperty(sponsor.name)) {
        byLocation[sponsor.location][sponsor.name] = [];
    }
    
    byLocation[sponsor.location][sponsor.name].push(event.title);
  });
  
});

console.log(byLocation);


To showcase the data within a <ul id="list"></ul>, in JavaScript:

const html = Object.entries(byLocation).reduce((h, [location, ob]) => {
  h += `<li>${location}<ul>`;
  Object.entries(ob).forEach(([sponsor, events]) => {
    h += `<li>${sponsor}
            <ul>
              <li>${events.join('</li><li>')}</li>
            </ul>
          </li>`;
  }); 
  h += `</ul></li>`;
  return h
}, ''); 

document.querySelector('#list').insertAdjacentHTML('beforeend', html);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using React as a dependency for @vue/apollo-composable allows for seamless integration of Apollo

My VueJs application is built using the Composition API. I am trying to implement Apollo for making queries to my GraphQL backend, but I keep encountering an error stating Could not resolve "react". The dependencies in my project include: "@apollo/client" ...

Leveraging Jquery Splice

Trying to eliminate an element from an array using the Splice method. arrayFinalChartData =[{"id":"rootDiv","Project":"My Project","parentid":"origin"},{"1":"2","id":"e21c586d-654f-4308-8636-103e19c4d0bb","parentid":"rootDiv"},{"3":"4","id":"deca843f-9a72 ...

A guide on integrating MySQL table data into React card elements

After successfully populating a React table within a card (see first code snippet below) with MySQL table data, I am now faced with the challenge of populating a card's information with the same SQL data. The image below displays how cards are curren ...

Control the frequency of server requests within a set limit

Currently, I am utilizing the request-sync library to fetch data from a specific site's API. This is how my code looks: let req = request('GET', LINK, { 'headers': { 'Accept' ...

generate a dynamic dropdown menu using ajax to handle a vast amount of information

I have been tackling a challenge involving codeigniter and ajax. Specifically, I am working with two select boxes - one for countries and another for states. The goal is to dynamically populate the states select box based on the selected country using an a ...

Implementing Object.somefunction() in ngFor with Angular

In my Angular project, I am using an ngFor loop to iterate over keys generated by Object.keys() in the following code snippet: <ul id='nav-tablist' class='tabrows'> <li *ngFor="let tab of obj.keys(tabList)"> ...

Sending a message to an iframe from a different origin using JavaScript

Just starting out with JavaScript and I'm attempting to send a message to my iframe in order to scroll it. Here is the code I am using: scroll(i) { var src = $("#iframe").attr("src"); $("#iframe").contentWindow.postMe ...

What is the best way to change a canvas into an image while preserving transparency?

Currently, I am attempting to modify a weather radar image with a black background by making the background transparent using canvas. However, when I view the modified image, instead of transparency, the background now appears as a red and black checkerboa ...

Animations are failing to run within a Bootstrap card when using Vue rendering

I have utilized Bootstrap cards to display pricing information in my project. I implemented a collapse feature for half of the card when the screen size is equal to mobile width. While using vanilla Bootstrap, the animation worked seamlessly with the col ...

In Vue, the concept of using the debounce method is not clearly defined

I am aware that using the arrow syntax for a method can cause 'this' to not be mapped to the Vue instance. In my case, I am utilizing lodash.debounce and I don't think I'm using the arrow syntax here? Encountering Error: Cannot read pr ...

Calculate inner product without using IML

I'm working on creating a macro that calculates the inner product of a vector and a matrix. Y*X*t(Y) ## equivalent to the Sum(yi*Xij*yj) Since I don't have IML, I'm attempting to accomplish this through array manipulation. Is there a ...

Navigating jQuery Tabs by Linking to a Specific Tab in a Separate File

I am currently using Bootstrap 3 to develop a basic website. On the about.html page, I have set up Tabs with various content. <ul class="nav nav-tabs" id="TabSomos"> <li class="active"><a href="#somos" data-toggle="tab">About Us</a> ...

Using JavaScript and AJAX to manage and control a shell interface

Looking to create an HTML page that includes a YouTube video and utilizes JavaScript with the YouTube API. The objective is to embed a video and test if it has been fully downloaded using the YouTube API. I have set up an Apache server with MySQL and PHP ...

A dynamic Angular search box designed for filtering columns in a table

I have a functioning table code that displays data related to domains: Now, I would like to enhance this table by adding a dynamic search box specifically for filtering the column named domain. As the user types in new characters in the search box, the ta ...

Ways to extract information from a JSON array

Having trouble extracting the driverId from this JSON data. [data: [{"id":"619","driverId":"6789","starting_time":"2016-12-12 23:24:50","end_time":null}]] Below is my complete code: //selector Method SESSION_STATUS_REQUEST_COMPLETE func afterServiceStat ...

Unable to extract property from object in context due to its undefined status

Having trouble with the useContext hook in my React app for managing the cart state. Keep getting an error stating that the function I'm trying to destructure is undefined. I'm new to using the context API and have tried various solutions like e ...

Which is better for managing checkbox state in React - react-bootstrap or material-ui?

Currently, I am working on a project that involves using checkboxes within a component to display products based on specific features selected by the user. I am seeking advice on how to effectively manage the checkboxes and their corresponding state inform ...

updating the row of an html table with elements from a javascript object

I am faced with the task of dynamically adding rows to a table based on the number of elements in my JavaScript object. The object consists of keys and arrays of values. userobject={ ID: [1,2,3] IP_Address: ["12.21.12 ...

Tips for creating animations with multiple elements that share the same classes

I am trying to create expandable boxes that can open onclick and close again by clicking on the X. The issue I'm facing is that the close jQuery function isn't working. However, my main concern is how to optimize the code so it doesn't becom ...

Tips for utilizing components in slots in Cypress and Vue for effective component testing

Can someone help me figure out how to import a component into a slot using Cypress Component Testing with Vue? The documentation mentions the following for slots: import DefaultSlot from './DefaultSlot.vue' describe('<DefaultSlot />& ...