3

I have a very unique problem that I am attempting to solve:

I have the following serialized query string:

a=a2&b.c=c2&b.d.e=e2&b.d.f=f2

Deserialized into the following object object:

{
    a: "a2", 
    b.c: "c2", 
    b.d.e: "e2", 
    b.d.f: "f2"
}

With the following parser (which works great on flat objects!)

function parse(string){
    string = 
    '{"' +  //root
        string
            .replace(/&/g, '","') //replace '&' with ','
            .replace(/=/g,'":"')+ //replace '=' with ':'\
    '"}'; //close root


return JSON.parse(string,function(key, value){ //handle URI issues

        var ret;

        if(key===""){ //null key means that we have something wrong with the encoding, probably escaped shit
            ret = value;
        }
        else{
            ret = decodeURIComponent(value); //decode escaped stuff
        }
        return ret;

});

}

This needs to be parsed into a multi-dimensional object, representational of the . notation within the keys, as such:

{
    a:"a2",
    b:{
        c: "c2",
        d:{
            e:"e2",
            f:"f2"
        }
    }
}

Any help here would be amazing. I've been trying to recurse this into shape of the past few hours, but my brain has fallen apart and there is no joy to be had in a solution.

If there is another method to parse a N'th dimensional javascript object into a URI and then back into a JavaSCript object (two functions), I am all ears.

georg
  • 211,518
  • 52
  • 313
  • 390
Andrew Rhyne
  • 5,060
  • 4
  • 28
  • 41

2 Answers2

0

You could serialize your javascript object and URL encode it, see this answer to a similar question: Standardized way to serialize JSON to query string?

Community
  • 1
  • 1
johnnynotsolucky
  • 540
  • 3
  • 16
0

I encountered the same problem out in the wild. Here's what I came up with:

const queryToObject = (query) => {

    return query.split('&').reduce((result, entry) => {
        const [k, v] = entry.split('=')
        const keys = k.split('.')
        let key = 'result', value = `'${v}'`
        for (i = 0; i < keys.length; i++) {
            key += `['${keys[i]}']`
            if (i == keys.length - 1) eval(key + '=' + value)
            else if (!eval(key)) eval(key + '= {}')
        }
        return result
    }, {})

}

and

const recursiveQueryToObject = (query) => {

    const helper = (keys, value, nth) => {
        const key = keys.shift()
        if (!keys.length) return { [key]: value }
        else return { [key]: { ...nth[key], ...helper(keys, value, nth[key] || {}) } }
    }

    return query.split('&').reduce((result, entry) => {
        const [k, value] = entry.split('=')
        const keys = k.split('.')
        const key = keys.shift()
        result[key] = keys.length ? { ...result[key], ...helper(keys, value, result[key] || {}) } : value
        return result
    }, {})

}