How can you transform square bracket object keys from a URL address into a nested object using Javascript?

Considering the following:

var obj = { "object[foo][bar][ya]": 100 };

Is there a way to achieve this structure:

var obj = { object: { foo: { bar: { ya: 100 }}}};

Answer №1

Step-by-step method

Begin by splitting the provided string using brackets, then proceed to create a nested object by iterating through the resulting tokens:

Initial String

var obj = { "object[foo][bar][ya]": 100 };

Split the string to obtain

var tokens = Object.keys(obj)[0]
    .split('[')
    .map(function(s){return s.replace(']','')});
    // tokens = [ 'object', 'foo', 'bar', 'ya' ]

Next, construct the nested object, starting from the innermost level

var result = {};
tokens.reverse().forEach(function(key){
    if (Object.keys(result).length==0){
        result[key] = obj[Object.keys(obj)[0]]; // inner-most key-value
    }
    else{
        var temp = {};
        temp[key] = result;
        result = temp;
    }
});

Final Output

{"object":{"foo":{"bar":{"ya":100}}}}

Answer №2

JavaScript does not have built-in functionality for parsing nested objects in query strings.

One recommended tool for this task is , which is highly effective.

console.log(URI.parseQuery("?&foo=bar&&foo=bar&foo=baz&"));

If you prefer not to import the entire library, you can use just the query string parsing part (credit to https://github.com/medialize/URI.js):

var URI = {
  decodeQuery: function(string, escapeQuerySpace) {
    string += '';

    try {
      return decodeURIComponent(escapeQuerySpace ? string.replace(/\+/g, '%20') : string);
    } catch(e) {
      // Handling unforeseen encodings, returning the original string
      return string;
    }
  },
  parseQuery: function(string, escapeQuerySpace) {
    if (!string) {
      return {};
    }

    // Cleaning up the query string
    string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, '');

    if (!string) {
      return {};
    }

    var items = {};
    var splits = string.split('&');
    var length = splits.length;
    var v, name, value;

    for (var i = 0; i < length; i++) {
      v = splits[i].split('=');
      name = URI.decodeQuery(v.shift(), escapeQuerySpace);
      value = v.length ? URI.decodeQuery(v.join('='), escapeQuerySpace) : null;

      if (Object.prototype.hasOwnProperty.call(items, name)) {
        if (typeof items[name] === 'string') {
          items[name] = [items[name]];
        }

        items[name].push(value);
      } else {
        items[name] = value;
      }
    }

    return items;
  }
};

Answer №3

If you source the necessary components, you have the option to construct a novel item.

const obj = {
    "object[foo][bar][ya]": 100,
    "object[foo][baz]": 200,
    "object[foo][bar][bar]": 50,
    "xy": 30
};

let newObj = {};

for (const i in obj) {
    let a = i.match(/([^\[\]]+)(\[[^\[\]]+[^\]])*?/g),
        p = obj[i];
        j = a.length;

    while (j--) {
        q = {};
        q[a[j]] = p;
        p = q;
    }
    // merge object
    let k = Object.keys(p)[0],
        o = newObj;

    while (k in o) {
        p = p[k];
        o = o[k];
        k = Object.keys(p)[0];
    }

    o[k] = p[k];
}

console.log(newObj);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №4

Presented below is an ES6 version of the code. Please note that it has not been thoroughly tested for all possible scenarios.

const keyPattern = /^(\w+)\[(\w+)\](.*)$/;

export function decodeParams(params) {
  return Object.keys(params).reduce((result, key) => {
    let match = key.match(keyPattern);

    if (match && match.length >= 3) {
      let [key, nextKey, rest = ''] = match.slice(1);

      result[key] = Object.assign(
        {},
        result[key],
        decodeParams({ [nextKey + rest]: params[key] })
      );
    } else {
      result[key] = params[key];
    }

    return 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

Discover the process of attaching an event to the keyboard display within a Cordova application

I've exhausted my efforts trying to figure out how to assign an event for when the virtual keyboard appears on my hybrid cordova app. I'm looking to trigger a specific action whenever the keyboard shows up in my app consistently. ...

Retrieve the jquery.data() of an element stored in an HTML file using JavaScript or jQuery

I have a dilemma with storing HTML in a database for later retrieval. Imagine the HTML being a simple div, like this: <div id="mydiv">This is my div</div> To store related information about the div, I use jQuery.data() in this manner ...

Guide to effectively invoking JavaScript functions using jQuery

<head> <script src="jquery-latest.js" /> <script> function resetValues(){ alert('Inside the resetValues function'); //using hexadecimal routine 1 -> 3 -> 5 -> 8 -> (11 == a) document.getElementB ...

List the properties that the arguments object supports

During a NodeJS interview, I was presented with the following question: What properties are supported by the arguments object? a) caller b) callee c) length d) All Upon researching, I discovered that all 3 mentioned properties are supposed to be present ...

Service injection results in an error

I am encountering an issue while trying to inject a service into a component, and the error message I receive is as follows: EXCEPTION: TypeError: Cannot read property 'getDemoString' of undefined It appears that the service is not being prop ...

The frequency of database updates exceeds expectations - involving vue.js this.$router.push and express operations

Having some trouble updating a MongoDB with this code. It seems to be updating three times instead of just once due to having three dates in the posts.date field. Utilizing Vue, Mongo, and Express for this project, I have the following data structure: { ...

Utilizing the zIndex property on a map label does not produce any impact when combined with a GeoJSON layer

Utilizing the Google map label tool, I am trying to showcase certain property from GeoJSON data on a GeoJSON layer. However, the issue arises as the layer has a dark color and the label is appearing blurry behind the GeoJSON data layer. Despite attempting ...

The directive code takes precedence over the controller code and is executed first

A custom directive has been implemented and is utilized as shown below: <div car-form car="car" on-submit="createCar(car)"></div> This directive is used on both the new and edit pages, each with its own controller. The EditCarController retri ...

Only initiate an AJAX call if there are no other pending AJAX requests from prior function invocations

Arriving at a new, chaotic code base with no testing available has presented me with a significant challenge. I am currently struggling to resolve an issue without the use of ES6, only relying on plain vanilla JS and jQuery. The scenario: Within a web pag ...

Can a complete form be encapsulated within a single AngularJS directive?

While I have come across several instances of individuals utilizing a blend of HTML and directives to craft an AngularJS form (as seen here), my goal is to develop a self-contained widget. This widget would encompass all the necessary HTML for the form w ...

What is causing my tooltips to flicker in Firefox but not in Chrome?

When I tried viewing the provided fiddle in Firefox (version 5.0.1 on a Mac), I noticed that when hovering over a day in the calendar and placing the mouse pointer inside the tooltip, the tooltip would flash on and off. Interestingly, this issue did not oc ...

What is a method to mimic the presence of JavaScript using PHP Curl?

Is it possible to parse HTML code from a webpage using PHP Curl even if there is an error message stating that JavaScript is required to access the site? Can PHP Curl be used to enable JavaScript on a webpage? ...

Having difficulty attaching events to Bootstrap 3 button radios in button.js

Struggling with extracting the correct value from a segmented control created using the radio button component of button.js in Twitter Bootstrap 3. Upon binding a click event to the segmented control and running $.serialize() on its parent form, I noticed ...

An effective method for creating responsive layouts for custom-shaped HTML elements in a board game

Can anyone guide me on aligning spaces responsively on a board in HTML using Angular 1.x? I've tried using vw/vh's and %s, but consistency breaks on different view sizes. Any straightforward suggestions to address this issue? Avoiding multiple c ...

Is there a way to export the HTML table content to an Excel sheet that is compatible with browsers such as Internet Explorer, Mozilla Firefox, and others?

Welcome to my HTML Page! <html> <head> <title>Table </title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"> </script> <script> </script> </head> <body> <table ...

Reveal unseen information on the webpage upon clicking a link

I have successfully implemented a fixed header and footer on my webpage. The goal is to make it so that when a user clicks on a link in either the header or footer, the content of that page should appear dynamically. While I have explored various styles, ...

Configuring download destination in WebDriver with JavaScript

I am trying to change the default download directory for Chrome using JavaScript (TypeScript). I attempted to set options like this: let options = webdriver.ChromeOptions; options.add_argument("download.default_directory=C:/Downloads") let driver = webd ...

Troubleshooting Knockout.JS: Why self.myObservable is not working and the importance of code organization

My webpage uses knockout to handle a search field, dropdown selection, and page number. These elements are all initialized with default values for the first run or when the page is accessed. I'm encountering an error that says: "self.selectedTeamId i ...

Difficulty encountered in resetting progress bar post ajax form submission

Hello, I hope you can assist me with an issue I am facing regarding my progress bar. After submitting the form using AJAX to insert data, my progress bar does not reset. I would like it to reset after clicking the submit button. The progress bar is speci ...

Is there a more efficient method to execute this AJAX request?

$('#request_song').autocomplete({ serviceUrl: '<%= ajax_path("trackName") %>', minChars:1, width: 300, delimiter: /(,|;)\s*/, deferRequestBy: 0, //miliseconds params: { artists: 'Yes' }, onSelect: functi ...