7

How do you convert a dotted keys into a javascript object and retain it's value?

So I got this kind of response from an API and I need to parse it by key: value.

{
  "property": "personal_info.address.city",
  "description": "Missing field"
},
{
  "property": "personal_info.address.country",
  "description": "Missing field"
},

So I achieved this:

{
    'personal_info.address.city': 'Missing field',
    'personal_info.address.country': 'Missing field'
}

// by using this code (lodash)

_.mapValues(_.keyBy(obj, 'property'), function(o) {
  return o.description;
})

however, i need it to be like this:

{
    personal_info: {
        address: {
            city: 'Missing field',
            country: 'Missing field',
        }
    }
}

I somehow searched in stackoverflow how to convert a dot notation string into an object here: Convert string with dot notation to JSON

but I'm stuck since I'm changing the key itself.

EDIT: Changed test city and test country to reflect the description field (sorry)

Angelo Ab
  • 125
  • 1
  • 8
  • Why is `country` not nested in `address`? Where does the `city` in `country` come from? How do you get from `Missing field` to `test city`? Please be more accurate. – str Mar 15 '18 at 15:10
  • @str my mistake, i didn't notice it at first. I already edited my question. Thanks for that! – Angelo Ab Mar 15 '18 at 16:05

2 Answers2

9

You could use _.set from lodash.

Sets the value at path of object. If a portion of path doesn't exist, it's created. Arrays are created for missing index properties while objects are created for all other missing properties. Use _.setWith to customize path creation.

var array = [{ property: "personal_info.address.city", description: "Missing field" }, { property: "personal_info.address.country", description: "Missing field" }],
    object = array.reduce((o, { property, description }) => _.set(o, property, description), {});

console.log(object);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
5

You could use forEach() loop and inside reduce() method to get result like this.

const data = [{"property": "personal_info.address.city","description": "Missing field"},{"property": "personal_info.address.country","description": "Missing field"}]

const result = {}
data.forEach(function(o) {
  o.property.split('.').reduce(function(r, e, i, arr) {
    return r[e] = (r[e] || (arr[i + 1] ? {} : o.description))
  }, result)
})

console.log(result)
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
  • That doesn't use the `description` property. – Scott Sauyet Mar 15 '18 at 15:17
  • The poster is using lodash, reinventing wheels hardly makes sense here. – georg Mar 15 '18 at 15:24
  • Thanks for this! The snippet works but I'm accepting Nina's solution since I'm using lodash. To all, this works for people who does not have lodash. Just change `'test ' + e` to `o.description`. – Angelo Ab Mar 15 '18 at 16:59