Transform a series of JavaScript object keys into array(s) when they contain numbers

107 Views Asked by At

I have this object:

{
  name: "Gold's Gym Venice",
  "categories[0].alias": "gyms",
  "categories[0].title": "Gyms",
  "categories[1].alias": "healthtrainers",       
  "categories[1].title": "Trainers",
  "location.state": "CA",
  "location.city": "Venice",
  "location.zip_code": "90291",
  "location.display_address[0]": "360 Hampton Dr",
  "location.display_address[1]": "Venice, CA 90291"
}

... and am trying to transform it into this:

{
    name: "Gold's Gym Venice",
    categories: [
        { alias: "gyms", title: "Gyms" },
        { alias: "healthtrainers", title: "Trainers" }
    ],
    location: {
      state: "CA",
      city: "Venice",
      zip_code: "90291",
      display_address: [ "360 Hampton Dr", "Venice, CA 90291" ]
    }
}

I tried both of these answers. Each gives slightly different output—the second one gets closer—but neither handles keys with square bracketed numbers/array positions properly.

What's the best way to handle this?

1

There are 1 best solutions below

4
Damzaky On BEST ANSWER

I think we can use the method from this answer, here is an example code for the example you provided:

const deepSet = (obj, path, val) => {
    path = path.replaceAll("[", ".[");
    const keys = path.split(".");

    for (let i = 0; i < keys.length; i++) {
        let currentKey = keys[i];
        let nextKey = keys[i + 1];
        if (currentKey.includes("[")) {
            currentKey = parseInt(currentKey.substring(1, currentKey.length - 1));
        }
        if (nextKey && nextKey.includes("[")) {
            nextKey = parseInt(nextKey.substring(1, nextKey.length - 1));
        }

        if (typeof nextKey !== "undefined") {
            obj[currentKey] = obj[currentKey] ? obj[currentKey] : (isNaN(nextKey) ? {} : []);
        } else {
            obj[currentKey] = val;
        }

        obj = obj[currentKey];
    }
};

const result = {};

const originalObj = {
  'categories[0].alias': 'gyms',
  'categories[0].title': 'Gyms',
  'categories[1].alias': 'healthtrainers',       
  'categories[1].title': 'Trainers',
  'location.display_address[0]': '360 Hampton Dr',
  'location.display_address[1]': 'Venice, CA 90291'
};

for (const [key, value] of Object.entries(originalObj)) {
  deepSet(result, key, value);
}

console.log(result);