Developed a hierarchical JSON format using a JavaScript array

I am aiming to generate a properly structured nested JSON file from an array, with unique key values. Currently, I can only output the JSON without any nesting.

The desired structure to be displayed in the console is :

{
    "Key" : "data1",
    "header" : {
        "title" : "data2",
        "tag1" : "data3",
        "tag2" : "data4"
    },
    "body" : {
        "text" : "data5"
    },
    "updates" : {
        "title" : "data6",
        "text" : "data7"
    },
    "footer" : {
        "title" : "data8",
        "row1" :{
            "col1" : {
                "title" : "data9",
                "text" : "data10"
            },
            "col2" : {
                "title" : "data11",
                "text" : "data12"
            }, 
            "col3" : {
                "title" : "data13",
                "text" : "data14"
            }
        },
        "row2" :{
            "col1" : {
                "title" : "data15",
                "text" : "data16"
            },
            "col2" : {
                "title" : "data17",
                "text" : "data18"
            }, 
            "col3" : {
                "title" : "data19",
                "text" : "data20"
            }
        },        
        "row3" :{
            "col1" : {
                "title" : "data22",
                "text" : "data23"
            },
            "col2" : {
                "title" : "data24",
                "titlebis" : "data25",
                "text" : "data26"
            }, 
            "col3" : {
                "title" : "data27",
                "text" : "data28"
            }
        },
        "row4" :{
            "col1" : {
                "title" : "data29"
            },
            "website" : "data30",
            "website-link" : "data31",
            "email" : "data38",
            "privacy" : "data32",
            "privacy-link" : "data33",
            "adr" : "data34",
            "adr2" : "data35"
        }        
    },
    "other" : {
        "short" : {
            "des" : "data36"
        },
        "promovideo" : "data37"
    }
}

Here is my current progress:

  var data = [["Key", "data1"],
    ["header.title", "data2"],
    ["header.tag1", "data3"],
    ["header.tag2", "data4"],
    ["body.text", "data5"],
    ["updates.title", "data6"],  
    ["updates.text", "data7"], 
    ["footer.title", "data8"],
    ["footer.row1.col1.title", "data9"],
    ["footer.row1.col1.text", "data10"],
    ["footer.row1.col2.title", "data11"],
    ["footer.row1.col2.text", "data12"],
    ["footer.row1.col3.title", "data13"],
    ["footer.row1.col3.text", "data14"],
    ["footer.row2.col1.title", "data15"],
    ["footer.row2.col1.text", "data16"],
    ["footer.row2.col2.title", "data17"],
    ["footer.row2.col2.text2", "data18"],
    ["footer.row2.col3.title", "data19"],
    ["footer.row2.col3.text", "data20"],
    ["footer.row3.col1.title", "data22"],
    ["footer.row3.col1.text", "data23"],
    ["footer.row3.col2.title", "data24"],
    ["footer.row3.col2.title", "data25"],
    ["footer.row3.col2.text", "data26"],
    ["footer.row3.col3.title", "data27"],
    ["footer.row3.col3.text", "data28"],
    ["footer.row4.col1.title", "data29"],
    ["footer.row4.website", "data30"],
    ["footer.row4.website-link", "data31"],
    ["footer.row4.email", "data31"],
    ["footer.row4.privacy", "data32"], 
    ["footer.row4.privacy-link", "data33"],
    ["footer.row4.adr", "data34"],
    ["footer.row4.adr2", "data35"],
    ["other.short.des", "data36"],
    ["other.promovideo", "data37"],
  ];
  // console.log(data);

  data.sort(alphabetical); // Sort alphabetically our 2D array
  
  CreateAndDisplayJson(data);

  // Convert Keys + Data Array to JSON
  function CreateAndDisplayJson(GetKeysTraductionArrayData) {
    var length = GetKeysTraductionArrayData.length;
  var output = "{\n";
  
  for (var i = 0; i < GetKeysTraductionArrayData.length; i++) {
    var key = GetKeysTraductionArrayData[i][0];
    var trad = GetKeysTraductionArrayData[i][1];
    
    var nameSplit = key.split("."); // Determine JSON indentation based on key
    
    if(nameSplit.length>1) { // Indentation needed
      
      var closeBrace = "";
      var spacing = ""; // JSON indentation
      var saveSpacingTab = []; // Closing indentations
      
      for (j=0; j < nameSplit.length; j++){ // Add key + indentation
        output += spacing + "\"" + nameSplit[j] + "\" : { \n";
        if (j==0 && i != GetKeysTraductionArrayData.length-1) { 
          closeBrace = spacing + "}, \n";
        } else {
          closeBrace = spacing + "} \n";
        }
        spacing += "   ";
        saveSpacingTab[j] = closeBrace;
        closingText = "";
        
        if (j == nameSplit.length - 1) { // Last key indentation
          saveSpacingTab.reverse();
          for (k=0; k < saveSpacingTab.length ; k++) { // Bracket indentation
            closingText += saveSpacingTab[k];    
          }
          output += spacing + "\"" + nameSplit[j] + "\" : " + "\"" + trad + "\"\n" + closingText; // last Row
        }
      }
    } else {
      output += "\"" + key + "\" : " + "\"" + trad + "\", \n";
    }
  } 
  // output += "}" + outputCommented;
  output += "}";
  console.log(output);
  return output;
}

// Sort alphabetically our 2D array
function alphabetical(a, b) {
  var A = a[0].toLowerCase();
  var B = b[0].toLowerCase(); 
  
  if (A < B) return -1;
  if (A > B) return 1;
  return 0;
}

Answer №1

To achieve this, you can utilize a forEach loop to iterate through each key, then apply the split method to separate keys and finally employ the reduce function to construct a nested structure for each key.

var info = [["Key","data1"],["header.title","data2"],["header.tag1","data3"],["header.tag2","data4"],["body.text","data5"],["updates.title","data6"],["updates.text","data7"],["footer.title","data8"],["footer.row1.col1.title","data9"],["footer.row1.col1.text","data10"],["footer.row1.col2.title","data11"],["footer.row1.col2.text","data12"],["footer.row1.col3.title","data13"],["footer.row1.col3.text","data14"],["footer.row2.col1.title","data15"],["footer.row2.col1.text","data16"],["footer.row2.col2.title","data17"],["footer.row2.col2.text2","data18"],["footer.row2.col3.title","data19"],["footer.row2.col3.text","data20"],["footer.row3.col1.title","data22"],["footer.row3.col1.text","data23"],["footer.row3.col2.title","data24"],["footer.row3.col2.title","data25"],["footer.row3.col2.text","data26"],["footer.row3.col3.title","data27"],["footer.row3.col3.text","data28"],["footer.row4.col1.title","data29"],["footer.row4.website","data30"],["footer.row4.website-link","data31"],["footer.row4.email","data31"],["footer.row4.privacy","data32"],["footer.row4.privacy-link","data33"],["footer.row4.adr","data34"],["footer.row4.adr2","data35"],["other.short.des","data36"],["other.promovideo","data37"]]

let response = {}
info.forEach(([key, value]) => {
  key.split('.').reduce((result, item, index, array) => {
    return result[item] || (result[item] = array[index + 1] ? {} : value)
  }, response)
})

console.log(response)

Answer №2

An alternate approach without using ternary operators and utilizing the reduce function:

const data = [["Key","data1"],["header.title","data2"],["header.tag1","data3"],["header.tag2","data4"],["body.text","data5"],["updates.title","data6"],["updates.text","data7"],["footer.title","data8"],["footer.row1.col1.title","data9"],["footer.row1.col1.text","data10"],["footer.row1.col2.title","data11"],["footer.row1.col2.text","data12"],["footer.row1.col3.title","data13"],["footer.row1.col3.text","data14"],["footer.row2.col1.title","data15"],["footer.row2.col1.text","data16"],["footer.row2.col2.title","data17"],["footer.row2.col2.text2","data18"],["footer.row2.col3.title","data19"],["footer.row2.col3.text","data20"],["footer.row3.col1.title","data22"],["footer.row3.col1.text","data23"],["footer.row3.col2.title","data24"],["footer.row3.col2.title","data25"],["footer.row3.col2.text","data26"],["footer.row3.col3.title","data27"],["footer.row3.col3.text","data28"],["footer.row4.col1.title","data29"],["footer.row4.website","data30"],["footer.row4.website-link","data31"],["footer.row4.email","data31"],["footer.row4.privacy","data32"],["footer.row4.privacy-link","data33"],["footer.row4.adr","data34"],["footer.row4.adr2","data35"],["other.short.des","data36"],["other.promovideo","data37"]]

const result = data.reduce((all, [keys, val]) => {

    keys.split('.').reduce((obj, key, i, arr) => {

        if (i === arr.length - 1) {
            obj[key] = val;
        } else {
            if (!obj.hasOwnProperty(key)) {
                obj[key] = {};
            };
        }

        return obj[key];

    }, all);

    return all;

}, {});

console.log(result);

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

Uncovering the Mystery Behind the Repetitive Execution of useEffect in Next.js

I am working on a Time Tracking feature for my Next.js application. In the ./app/components/TimeTracking.tsx file, I have implemented the following component: 'use client'; import React, { useEffect, useState } from 'react'; import { u ...

Looking to duplicate the elements with the click of a button?

I am in need of assistance with my registration form. My goal is to move the elements contained within the <fieldset> tags to the end of a row when the user clicks the + button. The result you see initially has been recreated. Thank you for your s ...

I am having trouble displaying SASS styles in the browser after running webpack with node

In my current project for an online course, I am utilizing sass to style everything. The compilation process completes successfully without any errors, but unfortunately, the browser does not display any of the styles. The styles folder contains five file ...

The request to sign up at http://localhost:3000/api/signup resulted in a 400 (Bad Request

Having recently started working with the MEAN stack, I've run into some issues when trying to send registration data using http.post. Below is my server code: var express = require('express'), bodyParser = require('body-parser' ...

React JS is not allowing me to enter any text into the input fields despite my attempts to remove the value props

Currently, I am working on creating a Contact Form using React Js. I have utilized react bootstrap to build the component, but unfortunately, when attempting to type in the input fields, the text does not change at all. import React, {useState} from ' ...

Saving information in JSON format into MongoDB

I'm currently working on a project to create a digital card generator app using node.js. My goal is to store the card data in JSON format within a MongoDB database. I am utilizing mongoose ODM for this task, but it seems that mongoose does not directl ...

The Next JS build process is failing to generate certain paths

Issue with Anime Database App Deployment A problem arose when I developed an anime database app using Nextjs and deployed it on Vercel. Although the build was successful and the initial page rendered properly, only a few dynamic routes displayed correctly ...

Reduce and combine JavaScript files without the need for Grunt or Gulp

My project involves working with over 50 JavaScript files that I want to combine and compress to optimize file size and minimize HTTP requests. The catch is, the client's system does not have Node or npm installed. How can I accomplish this task witho ...

Guide on setting the href value within a $.each loop in AJAX requests

I am struggling with downloading a file within a thread. The issue I'm facing is that I can't set the file name in the href and download attributes, so when I attempt to download it, it shows no file available. However, I did realize that replaci ...

Update my function to be asynchronous by changing async: false to async: true using JQuery and Ajax

I've created a function in a JavaScript class that accesses a PHP file to retrieve information from a database. Although this function works well, I attempted to set the property async: true, and it caused the function to stop working. (I received th ...

Pull the Bootstrap radio value from hyperlink buttons

Is anyone else having trouble retrieving values of radio buttons using jQuery? Here are the radio buttons in question: <div class="input-group"> <div id="radioBtn" class="btn-group"> <a class="btn btn-warning radio-selector btn ...

When making an ajax call, I passed the data "itemShape" but on the URL page, an error appeared stating "Undefined index: itemShape"

Hello, I have been using an Ajax function to send data with the key itemShape. However, when I directly access the URL page or service page, it displays the following error: Notice: Undefined index: itemShape in C:\wamp64\www\inventory_so ...

Error: Call stack size limit reached in Template Literal Type

I encountered an error that says: ERROR in RangeError: Maximum call stack size exceeded at getResolvedBaseConstraint (/project/node_modules/typescript/lib/typescript.js:53262:43) at getBaseConstraintOfType (/project/node_modules/typescript/lib/type ...

Sharing data between controllers using factory in AngularJS is not supported

I attempted to share data between two controllers by using a factory. However, it seems that the data is not being shared properly between the two inputs. In the AppCtrl controller, I set Data.FirstName to be equal to lattitude. But when I switch over to ...

Sending data from local storage to ajax call

Below is the code snippet in question: $.ajax({ url: localStorage.getItem("isntagram link"), // url: "https://api.instagram.com/v1/users/self/feed?access_token=233291163.8a612cd.c49f77de073746e9a2f53116b720302e", met ...

Managing object methods in ReactJS state

Currently, I am utilizing the Google Maps API and have the following piece of code implemented: class App extends React.Component { state = { polygon: null, }; checkPoly() { if (this.state. ...

The mouse coordinates do not align with the drawing of a rectangle on the canvas

I am having some issues with drawing a rectangle on mouse drag over the canvas that is overlayed on an HTML5 video JS player. The rectangle is being drawn, but it does not align correctly with the mouse coordinates. I suspect that the canvas, which is ove ...

Creating a custom string subtype in TypeScript

I am currently working on developing a game called Risk using TypeScript and React hooks. This game is played on a map, so my first step was to design a MapEditor. The state of the Map Editor is as follows: export interface IMapEditorState { mousePos: ...

React JS is having trouble rendering an object that contains a list as one of its elements

I've been attempting to display the P_words list element with React using map: const f_data = { key: 2412, reviewed: 100, rating:4, P_words: [{ word: "Coolx", freq: 5 }, { word: "Dumbf&quo ...

Implementing Click-Activated Scroll-to-Div Feature in React

I need to implement a scroll-to-div feature in my React App. However, the current structure of my app is preventing me from passing refs as props correctly, making it challenging to utilize ref.current.scrollIntoView(). The layout of my code looks like th ...