Transforming an object into an array of its properties

I am looking to transform the following object:

{
        middleName: null,
        name: "Test Name",
        university: {
            country: {
                code: "PL"
            },
            isGraduated: true,
            speciality: "Computer Science"
        }
    }

into an array structure:

[{
        key: "name",
        propertyValue: "Test Name",
    },
    {
        key: "middleName",
        propertyValue: null,
    },
    {   
        key: "university.isGraduated",
        propertyValue: true,
    },
    {   
        key: "university.speciality",
        propertyValue: "Computer Science", 
    },
    {   
        key: "university.country.code",
        propertyValue: "PL"
    }];

I have come up with an algorithm for this conversion, however, I believe it can be improved. It's especially important that if there are nested objects within the main object, they should be represented using dot notation (e.g university.country: "value")

let arr = [];
    Object.keys(parsedObj).map((key) => {
        if (parsedObj[key] instanceof Object) {
            Object.keys(parsedObj[key]).map((keyNested) => {
                if (parsedObj[key][keyNested] instanceof Object) {
                    Object.keys(parsedObj[key][keyNested]).map((keyNestedNested) => {
                        arr.push({ 'key': key + '.' + keyNested + '.' + keyNestedNested, 'propertyValue': parsedObj[key][keyNested][keyNestedNested] })
                    })
                } else {
                    arr.push({ 'key': key + '.' + keyNested, 'propertyValue': parsedObj[key][keyNested] })
                }
            })
        } else {
            arr.push({ 'key': key, 'propertyValue': parsedObj[key] })
        }
    });

Any suggestions on how to enhance this algorithm would be greatly appreciated.

Answer №1

This function showcases a recursive implementation.

The code assumes that the object being processed contains only strings and objects as values. If your data includes additional data types, further modifications may be necessary.

const myObj = {
  middleName: null,
  name: "Test Name",
  university: {
    country: {
      code: "PL"
    },
    isGraduated: true,
    speciality: "Computer Science"
  }
}
const myArr = [];

function convertObjectToArray(obj, keyPrepender) {
  Object.entries(obj).forEach(([key, propertyValue]) => {
    if (typeof propertyValue === "object" && propertyValue) {
      const updatedKey = keyPrepender ? `${keyPrepender}.${key}` : key;
      convertObjectToArray(propertyValue, updatedKey)
    } else {
      myArr.push({
        key: keyPrepender ? `${keyPrepender}.${key}` : key,
        propertyValue
      })
    }
  })
}

convertObjectToArray(myObj);
console.log(myArr);

Answer №2

My approach would involve recursion while avoiding unnecessary intermediary arrays, unless dealing with a particularly large object. Here's an example:

function transform(obj, target = [], prefix = "") {
    // Iterate through the object keys
    for (const key in obj) {
        // Only handle "own" properties
        if (Object.hasOwn(obj, key)) {
            const value = obj[key];
            // Get the full key for this property, including prefix
            const fullKey = prefix ? prefix + "." + key : key;
            if (value && typeof value === "object") {
                // If it's an object...
                if (Array.isArray(value)) {
                    throw new Error(`Arrays are not valid`);
                } else {
                    // ...recursively call the function, providing the key as the prefix
                    transform(value, target, fullKey);
                }
            } else {
                // If not an object, push it to the array
                target.push({key: fullKey, propertyValue: value});
            }
        }
    }
    // Return the result
    return target;
}

Here is a live example:

const original = {
    middleName: null,
    name: "Test Name",
    university: {
        country: {
            code: "PL"
        },
        isGraduated: true,
        speciality: "Computer Science"
    }
};

function transform(obj, target = [], prefix = "") {
    // Iterate through the object keys
    for (const key in obj) {
        // Only handle "own" properties
        if (Object.hasOwn(obj, key)) {
            const value = obj[key];
            // Get the full key for this property, including prefix
            const fullKey = prefix ? prefix + "." + key : key;
            if (value && typeof value === "object") {
                // If it's an object...
                if (Array.isArray(value)) {
                    throw new Error(`Arrays are not valid`);
                } else {
                    // ...recursively call the function, providing the key as the prefix
                    transform(value, target, fullKey);
                }
            } else {
                // If not an object, push it to the array
                target.push({key: fullKey, propertyValue: value});
            }
        }
    }
    // Return the result
    return target;
}
const result = transform(original, []);
console.log(result);
.as-console-wrapper {
    max-height: 100% !important;
}

Note that the order of array entries in the output may not match the standard order of JavaScript object properties due to their unpredictable ordering behavior.

Answer №3

This is the most foolproof method I could come up with :D, no global variables required. Simply grab it and use it wherever you need!

const test = {
  middleName: null,
  name: "Test Name",
  university: {
    country: {
      code: "PL"
    },
    isGraduated: true,
    speciality: "Computer Science"
  }
};


function convertObjectToPropertiesByPath(inputObj) {
  let resultArray = [];
  let initialObject = {};

  const extractKeys = (obj, parentKey='') => {
    initialObject = resultArray.length === 0 ? obj : initialObject;
    const entries = Object.entries(obj);
    for(let i=0; i<entries.length; i++) {
      const key = entries[i][0];
      const value = entries[i][1];
      const isRoot = initialObject.hasOwnProperty(key);
      parentKey = isRoot ? key : parentKey + '.' + key;

      if(typeof value === 'object' && value !== null && !Array.isArray(value)){
        extractKeys(value, parentKey);
      } else {
       resultArray.push({ key: parentKey, property: value });
      }
    }
  };

  extractKeys(inputObj);
  return resultArray;
}

console.log(convertObjectToPropertiesByPath(test));

Answer №4

In my coding journey, I delved into creating a concise recursive function and an object for validation purposes.

let data = {
  middleName: null,
  name: "Test Name",
  university: {
    country: {
      code: "PL"
    },
    isGraduated: true,
    speciality: "Computer Science"
  }
}

function checkIfObject(obj) {
  return obj !== null && obj.constructor.name === "Object"
}

function retrieveValues(data) {
  let valuesArray = Object.keys(data).map(
    value => {
      return { key: value, value: checkIfObject(data[value]) ? retrieveValues(data[value]) : data[value] };

    });
  console.log(valuesArray);
}

retrieveValues(data);

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

Adding a key-value pair to an associative array using a foreach loop in PHP

When working with JSON data obtained from an API endpoint, I have a requirement to insert a key-value pair into an array. Below is the function I am using: $magazines = Magazine::all(); foreach ($magazines as $magazine) { $resul ...

Store image selection in state

I am currently working on building an imagePicker in ReactNative, but I am running into an issue when trying to select the image. The error message I am receiving is: TypeError: this.setState is not a function. (In 'this.setState ({ avatar: data}) &a ...

The print screen button in Internet Explorer is not functioning the same way as in other browsers when using JavaScript

Recently, I implemented a JavaScript code that restricts Normal users (non-professionals) from using print screen, Ctrl+A, and Ctrl+C functionalities on the browser. While this code works seamlessly on Firefox and Chrome, it seems to have intermittent su ...

Manipulating Arrays in JavaScript: Techniques for Extracting Values Buried in Nested Objects

I am working with an array of objects that contain multiple "Book" objects with dynamic keys. My goal is to filter the objects in the array to only include those that have at least one new "Book" object. For example: const arr = [ { id: '123&ap ...

Issue encountered: NPM error, unable to find solution for resolving dependency and addressing conflicting peer dependency

I am facing difficulties deploying my project on netlify due to NPM errors. Below are the dependencies: "dependencies": { "@angular/animations": "~15.1.1", ... (list of dependencies continues) ...

I am able to access the JSON file from the URL without any issues, but for some reason, I am unable to fetch it using $

(function(){ $(document).ready(function(){ $.getJSON('http://dev.markitondemand.com/MODApis/Api/v2/Quote/json?symbol=AAPL&callback=?', function(){console.log("function was run");}); }); }()) I recently delved into working with APIs. Ho ...

Aggregate data based on one column id and align it with data from another column id

My dataset consists of a large table with millions of rows, structured like this: CREATE TABLE mytable ( row_id bigint, col_id bigint, value double precision, timestamp timestamp ); The challenge I am facing includes the following constra ...

Determine the fill color attribute value of a rectangle using Testcafe paired with typescript

Here is a code snippet I need help with: <colored-item label="Label A" symbol-size-left="9.5" symbol-size-right="12" symbol-right="" symbol-left="<svg viewport="0 0 24 24" xmlns="http://www. ...

Creating Vue3 Component Instances Dynamically with a Button Click

Working with Vue2 was a breeze: <template> <button :class="type"><slot /></button> </template> <script> export default { name: 'Button', props: [ 'type' ], } </scr ...

When using Node.js, you may encounter the error message: "TypeError: brevo.ApiClient is not a constructor

My goal is to set up an automatic email sending system that, upon receiving details like name and email, will send a confirmation email to the provided email address with the message "subscribed." I've been working on this task for about 7 hours strai ...

Utilizing window.location.pathname in Next.js for precise targeting

Are you familiar with targeting window.location.pathname in NEXT.JS? I encountered a red error while using this code in Next.js const path = window.location.pathname console.log(path) // I am able to retrieve the pathname here Then { ...

Searching for duplicated packages in npm

npm dedupe is known to simplify the folder structure, but I want to have a clear view of any duplicate packages before proceeding. Is there a way to generate a list of duplicate packages before running the command? If not, are there any scripts available ...

Tips for selecting the correct date on a DatePicker using selenium?

I am facing an issue with my selenium test related to a date picker on a webpage. The task is to select a specific date (e.g., 14/2/2012) by clicking on the correct day. However, the date picker is generated using jQuery as shown in the code snippet belo ...

Is there a way to simultaneously display every element from two arrays?

Hey everyone, I'm facing an issue with printing duplicated data from my database on a Drupal website. I've written a function that queries the database to find duplicates and then merges the data from two arrays after identifying them. function ...

Avoid refreshing AJAX on browser back navigation

Describing my current situation: I have a scenario with 2 pages: - On page 1, it sends a request using $.ajax to receive JSON data for display. Then there is a button that when clicked, takes me to page 2. - After clicking the button and transitionin ...

What is the best way to retrieve a JSON attribute and save it into an array using JAVA?

I am currently working on verifying in my RestAssured TestNG test that each ReportCodeNbr in my JSON file has the correct UID value associated with it. Initially, I managed to achieve this by directly referencing each section of the JSON using a fixed ind ...

JavaScript Regular Expressions: Naming Conventions

While many of us are familiar with naming conventions in R, regular expressions remain uncharted territory for me and the most dreaded aspect of my programming endeavors. As I dive back into JavaScript, I am grappling with creating precise RegExp to valida ...

Does anyone have any insight on why I can't seem to remove an item from my list of tasks?

Having trouble with my React todo list. After submitting, the list item looks fine. I expect to be able to delete it by clicking on the item, but nothing happens. When I try to add another item, the page refreshes and all items are removed. The console ...

What is the best way to generate an @ symbol using JavaScript?

When coding in Javascript, a challenge I am facing is creating a variable that includes the @ symbol in a string without it being misinterpreted as something else, especially when dealing with URLs. Does anyone have any suggestions on how to handle this ...

Retrieve specific elements from an array based on the other elements present in the array

I am working with a result set that consists of various combinations from the following data structure: [ ["1st", "FELONY"], ["2nd", "FELONY"], ["3rd", "FELONY"], ["1st", "MISDEMEANOR"], ["2nd", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"]] For example, it co ...