Javascript dotted object keys to object - javascript

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)

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>

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)

Related

how to transform value string in object to new const js

i need to convert a object with have key value to new object that contain new const named form platform and have name to value in js how to do it?
posters: [
{ platform: facebook; name: ["user test1","user test2"] },
{ platform: instagram; name: ["Ig test1","Ig test2"] },
]
in to
posters: {
facebook: ["user test1","user test2"] ,
instagram: ["Ig test1","Ig test2"] ,
}
Your input array is invalid. There are no strings around your platform values, and you're separating your object properties with a semi-colon rather than a comma. So you would need to fix that in order to proceed.
It looks as if posters is a property within a larger object so this answer will take that into account.
Use reduce on the posters array to iterate over the objects in the array and return an object where the keys are the platform names, and the values the name arrays.
Since it looks like posters is within a larger object we'll rebuild the object using the spread syntax.
const data={posters:[{platform:"facebook",name:["user test1","user test2"]},{platform:"instagram",name:["Ig test1","Ig test2"]}]};
// Create a new object
const updated = {
// Spread out the old object into it
...data,
// And replace the old `posters` property with an
// object using `reduce`. Destructure the `platform`
// and `name` properties from the object, and then
// use them to add a key and a value to the initial
// object (`acc`/accumulator)
posters: data.posters.reduce((acc, obj) => {
const { platform, name } = obj;
acc[platform] = name;
return acc;
}, {})
};
console.log(updated);
Additional documentation
Destructuring assignment
const postersArray = [
{ platform: facebook, name: ["user test1","user test2"] },
{ platform: instagram, name: ["Ig test1","Ig test2"] }
]
const postersObject = postersArray.reduce((previous, current) => {
return {
…previous,
[current.platform]: current.name
}
},{})

matching two object by partial match javascript

I have these 2 objects, where I want to alter the value of a 2nd object by checking the value of the 1st object. But I'm stuck, I've prepared a sample below
const inputs = {
"firstname": "james",
"lastname": ""
}
const errors = {
firstname_error: false,
firstname_error_msg: "first name is invalid",
lastname_error: false, //make this true because inputs.lastname is false / empty string
lastname_error_msg: "last name is invalid",
}
Object.entries(inputs).forEach(([key, value]) => {
if(!value) {
//how to make errors.lastname_error to true if inputs.lastname is false empty string?
}
})
Use Square Bracket Notation to assign the value.
An object property name can be any valid JavaScript string, or anything that can be converted to a string, including the empty string. However, any property name that is not a valid JavaScript identifier (for example, a property name that has a space or a hyphen, or that starts with a number) can only be accessed using the square bracket notation. This notation is also very useful when property names are to be dynamically determined (when the property name is not determined until runtime).
Concatenate _error to they key which will target required key in error object.
const inputs = {
"firstname": "james",
"lastname": ""
}
const errors = {
firstname_error: false,
firstname_error_msg: "first name is invalid",
lastname_error: false,
lastname_error_msg: "last name is invalid",
}
Object.entries(inputs).forEach(([key, value]) => {
if (!value) {
errors[`${key}_error`] = true;
}
});
console.log(errors);
If you use Lodash library, refer to isEqual and intersection functions
I get the key value of inputs and in a for cycle i check if exist the relative key with "_error" in errors object and the value ok inputs[key] is not empty.
I use this code and work:
const inputs = {
"firstname": "james",
"lastname": ""
}
const errors = {
firstname_error: false,
firstname_error_msg: "first name is invalid",
lastname_error: false, //make this true because inputs.lastname is false / empty string
lastname_error_msg: "last name is invalid",
}
for (const key in inputs) {
if (errors.hasOwnProperty(`${key}_error`) && !inputs[key]) {
errors[`${key}_error`] = true;
}
}

How to destructure nested objects in for-loop

var users = [
{ user: "Name1",geo:{lat:'12',long:'13'} },
{ user: "Name2",geo:{lat:'12',long:'13'}, age: 2 },
{ user: "Name2",geo:{lat:'12',long:'13'} },
{ user: "Name3",geo:{lat:'12',long:'13'}, age: 4 }
];
Above is the array of objects.
Here is the for-loop I destructured and get user and age but I want lat and long also how will I do that ? I want it through destructuring and for-loop like I did with user and age
for (let { user, age = "DEFAULT AGE" } of users) {
console.log(user, age);
}
You can use this:
for (let {user, age = "DEFAULT AGE", geo: {lat, long}} of users) {
console.log(user, age, lat, long);
}
You have already successfully destructured user (simply by the property name in the object) and age (with a default value as well).
To use nested destructuring, step by step, simply put the property name geo in there as well, since that’s the next property on the objects you’re iterating over that contains your needed values:
{user, age = "DEFAULT AGE", geo} — this would yield {lat: "12", long: "13"} for geo.
To access the nested properties directly, follow the object structure:
{user, age = "DEFAULT AGE", geo: {}} — this would just validate that geo is indeed an object.
Then, list the properties you want to access in that object:
{user, age = "DEFAULT AGE", geo: {lat, long}} — this would yield "12" for lat and "13" for long.
You could even go a step further and rename those properties:
{user, age = "DEFAULT AGE", geo: {lat: latitude, long: longitude}} — this would yield "12" for latitude and "13" for longitude.
These are the basic cases for destructuring objects:
name means “just assign the entire value to name”.
{} means “check that the value to be destructured is an object or can be converted into one, i.e. is neither null nor undefined; create no variables”.
{ prop } means “get the value of prop as the variable prop”.
{ prop: rename } means “follow the prop property and get its value as the variable rename”1.
{ prop = value } means “get the value of prop as the variable prop, but assign value if prop yields undefined”2.
For the “rename” case, the rules apply recursively: rename is like name, so it can be replaced by {}, or { anotherProp }, or { anotherProp: anotherRename }, or { anotherProp = anotherDefault }, etc.
Other properties on the same object level may be added via commas, like {propA, propB}.
For arrays, similar cases exist: [] would validate that the value to be destructured is an iterable object; [a, b] has the same meaning as {0: a, 1: b}; etc.
1: Note that in the case of { prop: something } no variable prop is created.
2: “yields undefined” means that obj.prop would be equal to undefined which means either that the property exists and has the literal value undefined or that the property doesn’t exist.
If you're just trying to find a given user and return the geo for it, this will do:
users.find( u => u.user === 'Name1' ).geo;
Keep in mind, you would want to do some checks aginst your 'find result' before trying to use it. For example:
const user = users.find( u => u.user === 'Name1' );
if (user && user.hasOwnProperty('geo')) {
console.log(user.geo);
}

Access second level child in Json based on a variable

I'm currently working on a configuration service in my Angular 2 application, my current concern is about the utilization of eval in my code to retrieve a value in my configuration.
Here's a sample of my configuration file:
{
"application": {
"environment": "dev",
"displayMenu": false
},
"error": {
"title": "Title Error",
"message": "Error message"
}
}
I'm retrieving this JSON with a simple HTTP request, but now I would like to access an element with my get method defined like this:
get(key: any) {
return (eval("this._config." + key));
}
As you can see, there is an eval in my code that I would like to avoid. I'm forced to use eval to allow the developer to do .get('application.environment') and actually I don't find any others an easy possibility.
The only other way that I could see is to split the key on a "." and retrieve the right element in my JSON like it was a simple array. But with this solution, I would be stuck to one depth only.
You could use an array of your object keys you wish to view, then reduce that array returning the key of the object. If you wish to have a string as the object accessors you can easily use string.split('.') to create the array you can reduce.
const data = {
"application": {
"environment": "dev",
"displayMenu": false
},
"error": {
"title": "Title Error",
"message": "Error message",
"deeper": {
"evenDeeper": "You can get to any level"
}
}
}
const path = (keys, obj) => {
return keys.reduce((obj, key) => {
return typeof obj !== 'undefined'
? obj[key]
: void 0
}, obj)
}
console.log(
path(['application', 'environment'], data)
)
console.log(
path('error.message'.split('.'), data) // move the split inside the path function
)
console.log(
path(['error', 'deeper', 'evenDeeper'], data)
)
console.log(
path(['error', 'fail', 'damn'], data) // fail safe
)
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>

Searching on a variable-defined field with ElasticSearch

Here is the relevant code:
var field = String(querystring.parse(postData).field).toLowerCase();
var qryObj = {
"fields" : view_options,
"query":{
"term" : { field : value}
}
};
The variable 'field' will be a string, like "number", "date", etc. What I want to do is search the index only in the field that is defined in the variable 'field'. This code works if I hardcode the string, like this:
"term" : { "number" : value}
So can someone shed some light on a way to only search a specific field using a predefined variable instead of a string?
You can't use variables as keys in an Object literal. On the left of each :, identifiers themselves become the key's name rather than being evaluated as variables for their values.
console.log({ key: "value" }); // { key: 'value' }
console.log({ "key": "value" }); // { key: 'value' }
You'll have to build the Object first using bracket member operators, then apply it to the query object:
var term = {};
term[field] = value;
var qryObj = {
fields: view_options,
query: {
term: term
}
};
Update:
With ECMAScript 6, Object literals do now support computed keys using bracket notation for the key:
var qryObj = {
fields: view_options,
query: {
term: {
[field]: value
}
}
};

Categories

Resources