2

I'm working with a JSON validator that checks a give JSON object against a schema and returns errors if it doesn't match. One of the things I need to do is add missing attributes, but these could potentially be quite deep in the structure. The validator error returns the location of a missing attribute as a string in this format:

'data.thing1.thing2.thingN'

I can strip out the "data." bit easily enough, but I don't know how to translate the rest to correct object notation, in any depth. This is what I've got so far:

var attributeLineage = newField.split(".");
obj[attributeLineage[0]][attributeLineage[1]] = "";

So obviously this only works when there are only two levels of depth. I need to loop through the values in attributeLineage and link them all together to correctly construct the missing attribute in the given object, at any depth. How can this be done?

I might be missing something totally obvious, or going about it the wrong way, but I'm not sure how to proceed.

Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
Katharine Osborne
  • 6,571
  • 6
  • 32
  • 61

1 Answers1

1

Using reduce() method get the reference of the inner object and update the property using last element in split array.

var newField = 'data.thing1.thing2.thingN';
// split the string
var attributeLineage = newField.split("."),
  // get last element and remove it from splitted array
  prop = attributeLineage.pop();

var ob = {
  data: {}
};

// get the object reference
var obj = attributeLineage.reduce(function(o, k) {
  // return if nested object is defined 
  // else define and return it
  return o[k] || (o[k] = {}) && o[k];
}, ob);

// update the inner object property
obj[prop] = "hi";

console.log(ob);
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
  • I'm a bit stumped by this approach (though it's more helpful than the linked 'duplicate' answer). I thought you were creating ob as a test, but I don't think that's what you're doing? I have an existing object where the missing attribute needs to be appended. When I try your approach, o[k] is often undefined and obj always ends up undefined. I think the issue is that I need to append an attribute, not just fill in a value to an existing attribute. – Katharine Osborne May 31 '16 at 15:37
  • Ah cool! I had to change the return value of the reduce to: return o[k] || (o[k] = "") && o[k];, since the end attributes are never objects themselves, and left off this bit: obj[prop] = ""; – Katharine Osborne May 31 '16 at 15:56
  • 1
    @KatharineOsborne : end attribute from the split array is removed using `pop()` , so there is no need for that – Pranav C Balan May 31 '16 at 16:05