What is the best way to transform a JavaScript object into a chain of interconnected links?

My goal is to transform an object structure like the one below...

var obj1 = {
  firstName: 'John',
  lastName: 'Green',
  car: {
    make: 'Honda',
    model: 'Civic',
    revisions: [
      { miles: 10150, code: 'REV01', changes: },
      { miles: 20021, code: 'REV02', changes: [
        { type: 'asthetic', desc: 'Left tire cap' },
        { type: 'mechanic', desc: 'Engine pressure regulator' }
      ] }
    ]
  },
  visits: [
    { date: '2015-01-01', dealer: 'DEAL-001' },
    { date: '2015-03-01', dealer: 'DEAL-002' }
  ]
};

... into a flattened structure as shown below:

{
    "firstName": "John",
    "lastName": "Green",
    "car.make": "Honda",
    "car.model": "Civic",
    "car.revisions.0.miles": 10150,
    "car.revisions.0.code": "REV01",
    "car.revisions.0.changes": ,
    "car.revisions.1.miles": 20021,
    "car.revisions.1.code": "REV02",
    "car.revisions.1.changes.0.type": "asthetic",
    "car.revisions.1.changes.0.desc": "Left tire cap",
    "car.revisions.1.changes.1.type": "mechanic",
    "car.revisions.1.changes.1.desc": "Engine pressure regulator",
    "visits.0.date": "2015-01-01",
    "visits.0.dealer": "DEAL-001",
    "visits.1.date": "2015-03-01",
    "visits.1.dealer": "DEAL-002"
}

My initial attempt at this flattening process fell short, mainly due to repetitive code. I realized that a recursive approach is needed to handle nested objects and arrays efficiently. Any suggestions?

EDIT: While similar to other queries, this question focuses on a specific notation and the processing of nested objects and arrays simultaneously.

EDIT: I have also inquired about the reverse operation, unflattening, in another post.

Answer №1

Below is the TypeScript code snippet for flattening data:

export const flatten = (data: object, prefix: string = '') => {
  const result: { [key: string]: string | number | null } = {};

  Object.entries(data).forEach(([key, value]) => {
    if (typeof value === 'object') {
      Object.assign(result, flatten(value, `${prefix}${key}.`));
    } else {
      result[`${prefix}${key}`] = value;
    }
  });

  return result;
};

And here is the JavaScript version of the code:

export const flatten = (data, prefix = '') => {
  const result = {};

  Object.entries(data).forEach(([key, value]) => {
    if (typeof value === 'object') {
      Object.assign(result, flatten(value, `${prefix}${key}.`));
    } else {
      result[`${prefix}${key}`] = value;
    }
  });

  return result;
};

Answer №2

One way to achieve recursion is by creating a function to store keys in a string format.

var obj1 = {
  firstName: 'John',
  lastName: 'Green',
  car: {
    make: 'Honda',
    model: 'Civic',
    revisions: [
      { miles: 10150, code: 'REV01', changes: 0},
      { miles: 20021, code: 'REV02', changes: [
        { type: 'asthetic', desc: 'Left tire cap' },
        { type: 'mechanic', desc: 'Engine pressure regulator' }
      ] }
    ]
  },
  visits: [
    { date: '2015-01-01', dealer: 'DEAL-001' },
    { date: '2015-03-01', dealer: 'DEAL-002' }
  ]
};

function flatten(data, c) {
  var result = {}
  for(var i in data) {
    if(typeof data[i] == 'object') Object.assign(result, flatten(data[i], c + '.' + i))
    else result[(c + '.' + i).replace(/^\./, "")] = data[i]
  }
  return result
}

console.log(JSON.stringify(flatten(obj1, ''), 0, 4))

Answer №3

Check out this awesome code snippet to flatten a nested object in JavaScript:

function flattenObject(obj)
{
  var flattenedObj = {};
  (function flatten(element, path) {
    switch (typeof element) {
      case "object":
        path = path ? path + "." : "";
        for (var key in element)
          flatten(element[key], path + key);
        break;
      default:
        flattenedObj[path] = element;
        break;
    }
  })(obj);
  return flattenedObj;
}

var nestedObj = {
  firstName: 'John',
  lastName: 'Green',
  car: {
    make: 'Honda',
    model: 'Civic',
    revisions: [{
      miles: 10150,
      code: 'REV01',
    }, {
      miles: 20021,
      code: 'REV02',
      changes: [{
        type: 'asthetic',
        desc: 'Left tire cap'
      }, {
        type: 'mechanic',
        desc: 'Engine pressure regulator'
      }]
    }]
  },
  visits: [{
    date: '2015-01-01',
    dealer: 'DEAL-001'
  }, {
    date: '2015-03-01',
    dealer: 'DEAL-002'
  }]
};

console.log(flattenObject(nestedObj));

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

ASP.NET page experiences issues with executing Javascript or jQuery code

Having trouble with client scripts not functioning correctly on a child page that utilizes a master page. Looking for help to resolve this issue. <%@ Page Title="" Language="C#" MasterPageFile="~/Store.Master" AutoEventWireup="true" CodeBehind="NewSt ...

Placing jQuery scripts in Blogger platform: A guide

After finding the correct codes to solve my problem in previous questions, such as How do I get an image to fade in and out on a scroll using jQuery?, I came across this helpful code snippet: var divs = $('.banner'); $(window).scroll(function(){ ...

Is it possible for the $.post function to overwrite variables within the parent function?

Recently, I delved into the world of JavaScript and my understanding is quite limited at this point. So, please bear with me as I learn :-) I am working on a basic booking system that saves dates and user IDs in MySQL. The system checks if a particular da ...

Error: Unable to locate module: Issue: Unable to find '../components/charts/be.js' in '/vercel/workpath0/my-app/pages'

Having some trouble deploying my next.js app through Vercel. Everything works fine locally with the command 'npm run dev'. But when attempting to deploy it on Vercel using a Github remote repository, I encountered the following error: 18:07:58.29 ...

Floating navigation bar that appears and disappears as you scroll

My webpage has a dynamic navbar that consists of two parts: navbarTop and navbarBottom. The navbarTop should appear when the user has scrolled down more than 110 pixels, while the navbarBottom should show up when the user scrolls up. The issue I am facing ...

Unable to retrieve the image

When trying to fetch an image, I encountered the following error: Failed to load resource: the server responded with a status of 404 (Not Found) TopBar.jsx import { useContext } from "react"; import { Link } from "react-router-dom"; ...

Having trouble including a YouTube iframe code within the document ready function

I am having trouble getting the youtube iframe API code to work properly within my $(document).ready() function. When I try to add the code inside the function, the player does not load. However, when I move the code outside of the document.ready, the play ...

Utilizing the reduce method to process an object and return a collection of objects

I have a complex object that I'm trying to transform using the reduce method, but I'm struggling to figure it out... Here is the structure of my object: const object = { ... } My goal is to create a new object with keys that are a combinatio ...

What could be the reason for the ReferenceError that is being thrown in this code, indicating that '

let number = 1; console.log(number); Feel free to execute this basic code snippet. You may encounter an issue: ReferenceError: test is not defined, even though the variable was declared. What could be causing this unexpected behavior? ...

"The Django querydict receives extra empty brackets '[]' when using jQuery ajax post to append items to a list in the app

Currently, I am tackling a project in Django where I am utilizing Jquery's ajax method to send a post request. The csrftoken is obtained from the browser's cookie using JavaScript. $.ajax({ type : 'POST', beforeSend: funct ...

React Bootstrap Forms: The <Form.Control.Feedback> element is failing to display when the validation is set to false

Problem: I am facing difficulties with displaying the React Bootstrap <Form.Control.Feedback></Form.Control.Feedback> when the validation is false in my form implementation. Steps to Recreate: Upon clicking the Send Verification Code button, ...

Leveraging NestJs Libraries within Your Nx Monorepo Main Application

I am currently part of a collaborative Nx monorepo workspace. The setup of the workspace looks something like this: https://i.stack.imgur.com/zenPw.png Within the structure, the api functions as a NestJS application while the data-access-scripts-execute ...

Having trouble implementing server-side rendering with Styled-Components in Next JS

I attempted to resolve my issue by reviewing the code and debugging, but unfortunately, I couldn't identify the root cause. Therefore, I have posted a question and included _document.js, _app.js, and babel contents for reference. Additionally, I disa ...

The 'substr' property is not found in the type 'string | string[]'

Recently, I had a JavaScript code that was working fine. Now, I'm in the process of converting it to TypeScript. var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; if (ip.substr(0, 7) == "::ffff ...

Does the gltf loader in three.js have compatibility issues with Internet Explorer 11?

Despite the claims on the official website that gltf files should load in three.js scenes using IE11, I have been experiencing issues with the loader. Even the examples provided by three.js fail to work on Internet Explorer when it comes to loading gltf fi ...

I am experiencing difficulty typing continuously into the input box in reactJS

In one of my components, I have the capability to add and delete input fields multiple times. <> <form onSubmit={optimizeHandler}> <div className="filter-container"> {conditions.map((condition, index) => ...

Toggle visibility of various items in a to-do list, displaying only one item at a time with the use of JavaScript

I am currently working on a web project using the Laravel framework. I am struggling with implementing a feature where only the title of each to-do item is displayed, and when clicked, it should reveal the corresponding content. However, I have encountered ...

Ways to incorporate forms.value .dirty into an if statement for an Angular reactive form

I'm a beginner with Angular and I'm working with reactive Angular forms. In my form, I have two password fields and I want to ensure that only one password is updated at a time. If someone tries to edit both Password1 and Password2 input fields s ...

Inquiring about socket.io: How can an io emit its own signal?

I am currently working on implementing the emit event in an express router, and I'm attempting to pass a global.io variable. However, I've encountered an issue where despite adding the following code: io.emit('join','Tudis' ...

When attempting to send a POST request to /api/users/login, the system returned an error stating that "

Is there a way to make a post request to the mLab Database in order to determine if a user account already exists? The server's response states that the User is not defined. Can you please review my code? // @route post api/user/login# router.post(& ...