Javascript object remove nesting - javascript

I am have an object that looks like this in the console,
res.local.details > Object {role-details : {} }
so to access this I would need to do res.local.details['role-details']
Is is possible to make it so I can "explode" role-details into details so I can just do
res.locals.details
to access the attributes from role-details

Yes, objects in JS are mutable. If you want to reassign data from one part of your object to another, you can just do it like this:
const myObj = {
name: {
first: 'John',
last: 'Smith',
},
address: {
streetNo: '123',
streetName: 'Main St',
city: {
name: 'Exampletown'
}
}
}
myObj.address.city.name // resolves to Exampletown
myObj.address.city = myObj.address.city.name
myObj.address.city /// resolves to Exampletown

This can be done in several ways.
In this particular case, where details just has that one property, you can just do:
res.local.details = res.local.details['role-details'];
In a more generic situation, details might have other properties that you don't want to destroy with this operation. In that case you can use:
Object.assign(res.local.details, res.local.details['role-details']);
With this, res.local.details will keep all its properties (provided they don't have the same name as properties of role-details), including role-details (but which becomes kind of obsolete).
The same can be achieved with:
res.local.details = {...res.local.details, ...res.local.details['role-details']};

Related

Removing key in a JSON object but want to keep the original

I am trying to delete a key in variable a. However, i still want to keep the original variable value for another purpose. But somehow its alway overwrite the initial a.
This is the code that i wrote:
let a = [
{ firstName: 'Tony', lastName: 'Stack' },
{ firstName: 'Iron', lastName: 'Man' }
];
console.log('before',a);
delete a[0].firstName;
console.log('after',a);
Output:
I am expecting the first console.log will be printing out the initial value.
It's just confuse myself. I feel like i must have missed some knowledge here. Appreciate for any help. Thanks
You can use map and spread operator like below
let a = [
{ firstName: 'Tony', lastName: 'Stack' },
{ firstName: 'Iron', lastName: 'Man' }
];
let removed = a.map(({firstName, ...lastName}) => lastName);
console.log('before:',a)
console.log('after:', removed)
Well your question has two parts. First, the console.log showing the same value before and after. What happens is, Chrome's console doesn't like to keep track of complicated data like objects. So, when you log the variables with the console closed, Chrome will only remember the variable. Then, when you open the console it will read that variable and display it in the logs. However, if you leave the console open and refresh the page you should see the correct values being printed.
The second part, storing the object to use it for later, requires something known as deep cloning. Here is the reason why that is required and here is a post detailing how to do it.
Your code is working correctly. Refer here for a full answer. You can verify your answer by logging the firstName instead of the whole object.
let a = [
{ firstName: 'Tony', lastName: 'Stack' },
{ firstName: 'Iron', lastName: 'Man' }
];
console.log('before',a[0].firstName);
delete a[0].firstName;
console.log('after',a[0].firstName);
let a = [
{ firstName: 'Tony', lastName: 'Stark' },
{ firstName: 'Iron', lastName: 'Man' }
];
let b= {...a} // use spread operator to clone an array
console.log('before',a);
delete b[0].firstName;
console.log('after',b);

Creating Dynamic Keys In Object

I am struggling to create dynamic nested keys in javascript. My problem is that I need to have a object like this
{
"grandGrandFather": 'A',
"firstGrandFather": {
name: "AA",
children: {
first: 'AAA',
children: {
first: "AAAA"
}
}
},
"secondGrandFather": {
name: "AB",
first: 'ABA',
children: {
first: "ABAA",
second: "ABAB"
}
}
},
"thirdGrandFather": {
name: "AC",
children: {
name: "ACA"
}
}
}
Here problem is that I need to fetch these data from somewhere and I need to create these values dynamically. The prop creation begins from the first level and goes upto fourth level. So my question is how can I create dynamic keys in JS. Also I know you can create dynamic keys in JS like this:
var obj = {
prop1: "a",
prop2: "b",
prop3:'c'
}
obj['prop4'] = 'd';
Also I have been successful in creating a props to a level but when I need to stack these I get confused any help would be appreciated.
Further details about above object
In the above object I created I am getting data from database and I need to add firstGrandFather, secondGrandFather, thirdGrandFather dynamically. Also I don't know what their children props I need to define would be in the object. Some may have spouse,age,work props inside some may not also I don't know how many of these I would get. And these goes on for one or two more level.
In php it would be easy to create these in associative array easily but I am having hard time doing it in JS.
dynamic keys are possible in ES6+ Docs here
Basically, the syntax is:
obj[variable] = value;
Variable must contain a primitive value.
As for stacking, I'm afraid you have to get used to working with deep keys access with either dot or bracket notation. You can also assign a property of your object to a variable and then access its props.
So if obj is the object from your example:
const firstGrandfathersChildren = obj.firstGrandFather.children
It will have the following assigned:
{
first: 'AAA',
children: {
first: "AAAA"
}
}

Update dynamic object

I have an object :
{
...,
values: {},
...
}
values is empty by default.
Now I want to add dynamic object to this object :
[myDynamicProperty]: {
title: '...',
introduction: '...'
}
That's ok, I know how to do this. But, on other action, I have to add key: value or key: object to [myDynamicProperty], when I try something, I loose the values of my [myDynamicProperty]
I've tried to clone my initial object, but it doesn't work.
For sure, someone on stackoverflow has the solution.
You could take a two step approach by assigning a default object to myDynamicProperty and then assign the values to it.
This keeps all properties of object.values[myDynamicProperty] and changes only the given keys.
var object = {
values: {},
}
object.values[myDynamicProperty] = object.values[myDynamicProperty] || {};
Object.assign(object.values[myDynamicProperty], { title: '...', introduction: '...' });
If you are trying to convey that you are starting with an object such as:
var user = {
meta: {
first_name: "John",
last_name: "Smith"
}
}
and wish to add middle_name to the meta object property, then you should do the following.
Object.assign(user['meta'], {middle_name: "Harry"});
Note that the first object will be overwritten with values from the later object(s). The later object properties will take precedence over previous objects properties. See Mozilla for further details. WARNING: This is an ES6 feature, use a polyfill for backwards compatibility if necessary.

Dexie : How to add to array in nested object

I am using Dexie IndexedDB wrapper and I am trying to add an object to an existing array which in inside a nested object. The structure looks similar to below
{
Name : 'John',
age : 33,
tags : {
skill: [{
first: '.NET',
second: 'JAVA',
third: [{special1:'sleep'},{special2:'eat'}]
}]
}
}
I have tried many way to push object special3:'run' to skill.third but without success. My last attempt looked something like this
const pathObject = {};
const fullPath = 'result.tags.skill[3].third';
pathObject[fullPath] = {special3:'run'};
db.inspections.update(id, pathObject);
The object is added outside and not inside the array 'third' something like below
{
Name : 'John',
age : 33,
tags : {
skill: [{
first: '.NET',
second: 'JAVA',
third: [{special1:'sleep'},{special2:'eat'}]
}]
skill[3]: {
third: {special3:'run'}
}
}
}
I wish to know if there a way to add to arrays in nested object using Dexie if not is there a way to achieve this using indexeddb. Help is appreciated as problem is been holding back progress
The easiest is to use Collection.modify() with a callback function to mutate your model:
db.inspections.where('id').equals(id).modify(x =>
x.tags.skill[0].third.push({special3:'run'}) );
If you want to use a keypath containing array items, it is also possible, as arrays can be looked at as objects with numeric keys:
db.inspections.update(id, {"tags.skill.0.third.3": {special3:'run'}});

pg-promise, using named parameters with nested objects

Is it possible to reference nested objects, when using named parameters with pg-promise, like the following example?
var obj = {
name: 'John',
address: {
postcode: 'abc'
}
};
db.query('SELECT * FROM users WHERE postcode=${address.postcode} AND name=${name}', obj);
At the moment the reference to the nested object is not resolved with the value, e.g. ${address.postcode} is left as is and not replaced with 'abc' in the query string.
NOTE: This answer is no longer valid since v6.10.0 of pg-promise, which started supporting Nested Named Parameters natively.
And the code example provided in the question will just work as is.
Only for pg-promise prior to v6.10.0
The library only formats Named Parameters, it doesn't evaluate them, therefore no, you cannot do it, at least not directly like that.
But you can make sub-properties available to the query-formatting engine through functions:
var obj = {
name: 'John',
address: {
postcode: 'abc'
},
addrCode: a => a.address.postcode // alias for accessing a sub-property
};
and then use WHERE postcode = ${addrCode}.
And the older / ES5 syntax, via this works also:
var obj = {
name: 'John',
address: {
postcode: 'abc'
},
addrCode: function(/*a*/) {
// a = this (can use both)
return this.address.postcode;
}
};
UPDATE
It is possible to make client-side evaluations work, but only with $1, $2, ... parameters:
db.query('... postcode = $1 AND name = $2', [obj.name, obj.address.postcode]);
NOTE: You cannot use evaluations like ${obj.address.postcode} directly inside the query string, because the value won't be correctly escaped.

Categories

Resources