1

With:

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

How can I create:

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

4 Answers 4

4

Manual approach

Split the given string with bracket, then iterate through the resultant tokens to make the nested object:

Given

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

Split them so we get

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

Then make the nested object, inside out

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;
    }
});

Result

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

Sign up to request clarification or add additional context in comments.

2 Comments

That's not a very robust solution, but pretty clever way of doing it +1
@cyrbil Any suggestion is appreciated :) I always want to hear what people think.
3

Their is no native things in javascript fr parsing nested object in querystring.

You can use http://medialize.github.io/URI.js/ which is pretty damn good at the job.

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

If you don't want to import the full library, this is just the part for querystring parsing (full 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) {
      // we're not going to mess with weird encodings,
      // give up and return the undecoded original string
      // see https://github.com/medialize/URI.js/issues/87
      // see https://github.com/medialize/URI.js/issues/92
      return string;
    }
  },
  parseQuery: function(string, escapeQuerySpace) {
    if (!string) {
      return {};
    }

    // throw out the funky business - "?"[name"="value"&"]+
    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);
      // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters
      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;
  }
};

Comments

1

You could get the parts and build a new object.

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; }

Comments

0

Here's an es6 version. Caution: Hasn't been tested for edge cases.

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;
  }, {});
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.