1

I actually wish to convert a string to a deep object, but am pretty sure converting the string to an array is the first step. Let me explain.

I am using xeditable which by default will send {"name": "somePropertyName", "value": "someValue"} to the server, however, I wish to send {"somePropertyName": "someValue"}. I am able to accomplish this by setting $.fn.editable.defaults.params to the appropriate callback.

Now the part I am stuck on. I am using a special naming pattern that if the name has periods in it (i.e. name is a.b.c), I don't want to send {"a.b.c": "someValue"} to the server, but instead send {"a":{"b":{"c":"someValue"}}} to the server.

I've got a partially working version, however, it is not very elegant and more importantly I haven't gotten the last property working and have temporarily hardcoded it which is not acceptable.

How can this be accomplished?

$.fn.editable.defaults.params = function(params){
    return nvp2obj(params.name, params.value);
}

function nvp2obj(n, v, d) {
    d = d ? d : '.';
    n = n.split('.');
    var o = {};
    var r = o;
    n.reduce(function(total, currentValue, currentIndex, arr) {
        if(r) {
            r[currentValue]={};
            r=o[currentValue];
        }
        else {
            //this is obviously not correct
            o.a.b.c=v;
        }
        return o;
        }, o);
    return o;
}
var test = nvp2obj('a.b.c', 'someValue'); //{"a":{"b":{"c":"someValue"}}}
console.log('test', JSON.stringify(test));

2 Answers 2

4

You could iterate the given keys and assign the value by taking the last key.

function setValue(object, keys, value) {
    var last = keys.pop();
        
    keys.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
}

var test = {};
    
setValue(test, 'a.b.c'.split('.'), 'someValue');
setValue(test, 'a.d.e'.split('.'), 'someValue2');
setValue(test, 'a.b.a'.split('.'), 'someValue3');

console.log(test);

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

2 Comments

objects seems unused on your function, object seems to work anyway as it's global.
This is the best answer by far.
2

How about this:

function nvp2obj(n, v, d) {
  n = n.split(d || '.');
  n.reverse()
  return n.reduce(function(res, it) {
    return {[it]: res}
  }, v)
}


var test = nvp2obj('a.b.c', 'someValue');
console.log('test', JSON.stringify(test));

test = nvp2obj('a|b|c', 'someValue', '|');
console.log('test', JSON.stringify(test));

Loops through the keys from the end (starts with 'c'), first returning an object with the last key corresponding to the desired value ( {c: value} ). Then {b: {c: value}}, then {a: {b: {c: value}}}

2 Comments

what happens with the next value?
You mean if they want to add more keys and values to the same object afterwards as in your code? Not sure, don't think they specified that they need to do that.

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.