Combine two objects while keeping object name - javascript

I'm not totally sure if I'm using the correct terminology or not, I'm relatively new to node.
I have two JSON objects
const objA = {
key1: value1
...
}
const objB = {
key2: value2
...
}
that I want to combine into one while keeping the two object names, so it would look a bit like:
const newObj = {objA: { key1: value1,...}, objB: { key2: value2,...}}
So far in my research I've found Object.assign(objA,objB) which just combines them as newObj = {key1: value1, key2: value2, ...}
Is there a way to do what I want?

const newObj = {objA, objB};
You can assign them into new object like above.

Just putting it out there as a reference if you wanted to combine the key and values from both objects into one you could always use spread syntax if you decide to not go with a multi-level object:
const objA = {
key1: "value1"
}
const objB = {
key2: "value2"
}
const objCombined = {...objA, ...objB }
console.log(objCombined)

Related

Convert key value pair to array of objects

I have a key value pair:
`{good: 'value1', key2: 'value2': key3: 'value3'}
I want to convert it as the following:
[{key: 'good', value:'value1'}, {key: 'key2', value: 'value2'}, {key: 'key3', value: 'value3']
So far, I am able to convert them into an array with Object.entries, but I am unable to get my desired result.
There exists a method Object.entries that turns object into list of keys and values already, mapping it to match your required format should not be difficult.
const data = {good: 'value1', key2: 'value2', key3: 'value3'};
const result = Object.entries(data).map(([key, value]) => ({key, value}))
console.log(result)
You can do it like this:
const data = {good: 'value1', key2: 'value2', key3: 'value3'};
const result = [];
Object.keys(data).forEach(key => {
result.push({key, value: data[key]})
})
console.log(result)
To transform arrays, javascript provides a variety of array methods. map, foreach, reduce. etc. (Read more)
Object.entries( data ) converts your object into an array of arrays where each inner array is a key-value pair like this
[ [key1, value1], [key2, value2] ....]. (Read More)
Your usecase:
const data = { good: 'value1', key2: 'value2', key3: 'value3' };
const entries = Object.entries(data);
// [ ["good","value1"], ["key2","value2"],["key3","value3"] ]
// Map those entries to your desired form.
const results = entries.map( entry => ({ key: entry[0], value: entry[1] }) ) ;
// Or leverage the destructuring fetaure
// const results = entries.map( ([key, value]) => ({ key, value }) ) ;
console.log(results)
In case if you are interested in fast solution:
type Values<T> = T[keyof T]
type Mapper<T> = {
[Prop in keyof T]: { key: Prop, value: T[Prop] }
}
type Convert<T> = Array<Values<Mapper<T>>>
function convert<
Prop extends string,
Value extends string,
Obj extends Record<Prop, Value>
>(obj: Obj): Convert<Obj>
function convert<
Prop extends string,
Value extends string,
Obj extends Record<Prop, Value>
>(obj: Obj) {
const result: {
key: Extract<keyof Obj, string>;
value: Obj[Extract<keyof Obj, string>];
}[] = []
for (let prop in obj) {
result.push({
key: prop,
value: obj[prop]
})
}
return result
}
const result = convert({ good: 'value1', key2: 'value2', key3: 'value3' })
const first = result[0]
if (first.key === 'good') {
// {
// key: "good";
// value: "value1";
// }
first
}
Cons:
convert function creates internal result variable and mutates it. It is possible to use recursion instead of mutation result but I'm not sure this trade of worth it.
Pros
Faster than entries & map
Convert types maps type of argument to the type you want to achieve but only in type scope, whereas function maps argument in runtime scope.
If performance is not critical, you probably should stick with other solution where Object.entries is used

how to iterate a object array to get key and value in typescript

I have a object array and would like to get key and value by iterating though it, however I only get 0, 1 as index. anyone know why?
const vairable = [{key1: "value1"}, {key2: "value2"}]
Object.keys(vairable).forEach((i: any) => {
console.log(i); # get 0 and 1, I would like to have key1, key2
});
Object.keys gives the indices of the array itself, not the objects in the values. Iterate over the values and explore them:
const variable = [{key1: "value1"}, {key2: "value2"}];
for (const value of variable) {
const firstKey = Object.keys(value)[0];
console.log(firstKey);
}
Please try like this.
const vairable = [{key1: "value1"}, {key2: "value2"}]
vairable.forEach(item =>{
for (const [key, value] of Object.entries(item)){
console.log(key , value)
}
})
it will output :
key1 value1
key2 value2
How about this: Loop through array:
const vairable = [{key1: "value1"}, {key2: "value2"}]
for(let e of vairable) {
console.log(Object.keys(e))
}
The Object.keys method work on the Object not on the Arrays. If you want a loop through an Object, Then it will work fine like below,
const keys = {key1: "value1", key2: "value2"};
Object.keys(keys).forEach((key) => {
console.log(key);
});

Javascript - object keys / values

i want to know if i can set the same value for multiple keys in the following:
React functional component state:
const [state, setState] = useState(
key1: 'same-value',
key2: 'same-value',
key3: 'same-value'
);
React class component state:
state = {
key1: 'same-value',
key2: 'same-value',
key3: 'same-value'
};
Javascript object:
const state = {
key1: 'same-value',
key2: 'same-value',
key3: 'same-value'
};
I want to know if something like this is possible:
const state = {
state1, state2, state3: 'same-value';
};
I want to know if something like this is possible
Not in an object literal, no. You can do it after creating the object:
const state = {};
state.key1 = state.key2 = state.key3 = 'same-value';
Or you could make key2 and key3 accessor properties for key1, meaning they'd track its value (change key1, and you see the change in key2 and key3), because although using them looks like a simple property access, in fact it's a function call.
const state = {
key1: 'some-value',
get key2() { return this.key1; },
get key3() { return this.key1; }
};
console.log(state.key1); // 'some-value'
console.log(state.key2); // 'some-value'
console.log(state.key3); // 'some-value'
I'm not suggesting that, just noting it's possible.

Convert single element in array of objects

I am trying to convert all elements of a given key in a list of objects. The specific change is to convert an generic object to a Long object with the same values.
Input:
[obj1, obj2, obj3, ...]
Where each object looks like:
{
key1: value1, // value1 is an object
key2: value2
}
So the goal here is to get a very similar array, but where key1 is transformed from just object to a long object, in my example incremented by one.
Output:
[obj1, obj2, obj3]
Where each object is:
{
key1: value1, // value1 is now a Long object
key2: value2
}
I tried with mapping over the array and then spreading over the objects entries, but did not succeed.
Any help would be highly appreciated.
You don't really need to map here, unless you want to create one more new array. Simple loop would be enough, just update key1 or each object:
[obj1, obj2, obj3].forEach(obj => {
obj.key1 = obj.key1 + 1
})
Since the array holds object - any modification to object reflect the actual input being passed. You need to make a copy of your object and perform the logic.
Your logic,
var input = [obj1, obj2, obj3];
var output = input.map(function(obj){
obj.key1 = obj.key1 + 1;
return obj;
});
console.log(input[0]===output[0]); //true
Solution:
var output = input.map(function(obj){
var _objCopy = Object.assign({}, obj);
_objCopy.key1 = _objCopy.key1 + 1;
return _objCopy;
});
console.log(input[0]===output[0]); //false
how about dynamically first key of any object es6 way
const myObject0 = {
'foo1': { name: 'myNam1' },
'foo2': { name: 'myNam2' }
};
const myObject1 = {
'yo': { name: 'myNam1' },
'boh': { name: 'myNam2' }
};
[myObject0, myObject1].forEach(obj => {
let getFirstKey = Object.keys(obj)[0];
getFirstKey = getFirstKey + 1;
console.log(getFirstKey);
});
Thanks for all the answers guys.
I ended up with the following:
Given the input
[
{
key1: value1, // value1 is an object
key2: value2
},
{
key1: value1, // value1 is also an object
key2: value2
}
]
Solution:
I ended up with,
const testvar = [obj1, obj2, obj3].map((obj) => {
return {
...obj,
key1: new Long.fromValue(obj.key1)
}
});
console.log(testvar);
Which gives the output
[
{
key1: value1, // value1 is now a Long object
key2: value2
},
{
key1: value1, // value1 is also now a Long object
key2: value2
}
]

Combine or merge JSON on node.js without jQuery

I have multiple JSON like those
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
They are not nesting or anything like that. Just basically different fields. I need to combine them into one single JSON in node.js like this:
{name: "John", location: "San Jose"}
I can use jQuery just fine. Here is a working example in the browser:
http://jsfiddle.net/qhoc/agp54/
But if I do this in node.js, I don't want to load jQuery (which is a bit over use, plus node.js' jQuery doesn't work on my Windows machine).
So is there a simple way to do things similar to $.extend() without jQuery?
You should use "Object.assign()"
There's no need to reinvent the wheel for such a simple use case of shallow merging.
The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };
var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, target object itself is changed
console.log(obj === o1) // true
Even the folks from Node.js say so:
_extend was never intended to be used outside of internal NodeJS modules. The community found and used it anyway.
It is deprecated and should not be used in new code. JavaScript comes with very similar built-in functionality through Object.assign.
Update:
You could use the spread operator
Since version 8.6, it's possible to natively use the spread operator in Node.js. Example below:
let o1 = { a: 1 };
let o2 = { b: 2 };
let obj = { ...o1, ...o2 }; // { a: 1, b: 2 }
Object.assign still works, though.
**PS1**: If you are actually interested in **deep merging** (in which internal object data -- in any depth -- is recursively merged), you can use packages like [deepmerge][4], [assign-deep][5] or [lodash.merge][6], which are pretty small and simple to use.
**PS2**: Keep in mind that **Object.assign doesn't work with 0.X versions of Node.js**. If you are working with one of those versions (_you really shouldn't by now_), you could use `require("util")._extend` as shown in the Node.js link above -- for more details, check [tobymackenzie's answer to this same question](https://stackoverflow.com/a/22286375/36272).
If using Node version >= 4, use Object.assign() (see Ricardo Nolde's answer).
If using Node 0.x, there is the built in util._extend:
var extend = require('util')._extend
var o = extend({}, {name: "John"});
extend(o, {location: "San Jose"});
It doesn't do a deep copy and only allows two arguments at a time, but is built in. I saw this mentioned on a question about cloning objects in node: https://stackoverflow.com/a/15040626.
If you're concerned about using a "private" method, you could always proxy it:
// myutil.js
exports.extend = require('util')._extend;
and replace it with your own implementation if it ever disappears. This is (approximately) their implementation:
exports.extend = function(origin, add) {
if (!add || (typeof add !== 'object' && add !== null)){
return origin;
}
var keys = Object.keys(add);
var i = keys.length;
while(i--){
origin[keys[i]] = add[keys[i]];
}
return origin;
};
Underscore's extend is the easiest and quickest way to achieve this, like James commented.
Here's an example using underscore:
var _ = require('underscore'), // npm install underscore to install
object1 = {name: "John"},
object2 = {location: "San Jose"};
var target = _.extend(object1, object2);
object 1 will get the properties of object2 and be returned and assigned to target.
You could do it like this as well, depending on whether you mind object1 being modified:
var target = {};
_.extend(target, object1, object2);
A normal loop?
function extend(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) {
for (var prop in source) {
target[prop] = source[prop];
}
});
return target;
}
var object3 = extend({}, object1, object2);
That's a basic starting point. You may want to add things like a hasOwnProperty check, or add some logic to handle the case where multiple source objects have a property with the same identifier.
Here's a working example.
Side note: what you are referring to as "JSON" are actually normal JavaScript objects. JSON is simply a text format that shares some syntax with JavaScript.
Use merge.
$ npm install merge
Sample code:
var merge = require('merge'), // npm install -g merge
original, cloned;
console.log(
merge({ one: 'hello' }, { two: 'world' })
); // {"one": "hello", "two": "world"}
original = { x: { y: 1 } };
cloned = merge(true, original);
cloned.x.y++;
console.log(original.x.y, cloned.x.y); // 1, 2
I see that this thread is too old, but I put my answer here just in logging purposes.
In one of the comments above you mentioned that you wanted to use
'express' in your project which has 'connect' library in the
dependency list. Actually 'connect.utils' library contains a 'merge'
method that does the trick. So you can use the 3rd party
implementation without adding any new 3rd party libraries.
Here is simple solution, to merge JSON.
I did the following.
Convert each of the JSON to strings using JSON.stringify(object).
Concatenate all the JSON strings using + operator.
Replace the pattern /}{/g with ","
Parse the result string back to JSON object
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
var merged_object = JSON.parse((JSON.stringify(object1) + JSON.stringify(object2)).replace(/}{/g,","))
The resulting merged JSON will be
{name: "John", location: "San Jose"}
There is an easy way of doing it in Node.js
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
To combine/extend this we can use ... operator in ECMA6
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
var result = {
...object1,
...object2
}
console.log(result)
You can also use this lightweight npm package called absorb
It is 27 lines of code, 1kb and uses recursion to perform deep object merges.
var absorb = require('absorb');
var obj1, obj2;
obj1 = { foo: 123, bar: 456 };
obj2 = { bar: 123, key: 'value' }
absorb(obj1, obj2);
console.log(obj1); // Output: { foo: 123, bar: 123, key: 'value' }
You can also use it to make a clone or only transfer values if they don't exist in the source object, how to do this is detailed in the link provided.
It can easy be done using Object.assign() method -
var object1 = {name: "John"};
var object2 = {location: "San Jose"};
var object3 = Object.assign(object1,object2);
console.log(object3);
now object3 is { name: 'John', location: 'San Jose' }
Use spread operator. It is supported in Node since version 8.6
const object1 = {name: "John"};
const object2 = {location: "San Jose"};
const obj = {...object1, ...object2}
console.log(obj)
// {
// "name": "John",
// "location": "San Jose"
// }
If you need special behaviors like nested object extension or array replacement you can use Node.js's extendify.
var extendify = require('extendify');
_.extend = extendify({
inPlace: false,
arrays : 'replace',
isDeep: true
});
obj1 = {
a:{
arr: [1,2]
},
b: 4
};
obj2 = {
a:{
arr: [3]
}
};
res = _.extend(obj1,obj2);
console.log(JSON.stringify(res)); //{'a':{'arr':[3]},'b':4}
Lodash is a another powerful tool-belt option for these sorts of utilities. See: _.merge() (which is recursive)
var object = {
'a': [{ 'b': 2 }, { 'd': 4 }]
};
var other = {
'a': [{ 'c': 3 }, { 'e': 5 }]
};
_.merge(object, other);
// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
The below code will help you to merge two JSON object which has nested objects.
function mergeJSON(source1,source2){
/*
* Properties from the Souce1 object will be copied to Source2 Object.
* Note: This method will return a new merged object, Source1 and Source2 original values will not be replaced.
* */
var mergedJSON = Object.create(source2);// Copying Source2 to a new Object
for (var attrname in source1) {
if(mergedJSON.hasOwnProperty(attrname)) {
if ( source1[attrname]!=null && source1[attrname].constructor==Object ) {
/*
* Recursive call if the property is an object,
* Iterate the object and set all properties of the inner object.
*/
mergedJSON[attrname] = zrd3.utils.mergeJSON(source1[attrname], mergedJSON[attrname]);
}
} else {//else copy the property from source1
mergedJSON[attrname] = source1[attrname];
}
}
return mergedJSON;
}
You can use Lodash
const _ = require('lodash');
let firstObject = {'email' : 'email#email.com};
let secondObject = { 'name' : { 'first':message.firstName } };
_.merge(firstObject, secondObject)
A better approach from the correct solution here in order to not alter target:
function extend(){
let sources = [].slice.call(arguments, 0), result = {};
sources.forEach(function (source) {
for (let prop in source) {
result[prop] = source[prop];
}
});
return result;
}
You can do it inline, without changing any variables like this:
let obj1 = { name: 'John' };
let obj2 = { surname: 'Smith' };
let obj = Object.assign({}, obj1, obj2); // { name: 'John', surname: 'Smith' }
Let object1 and object2 be two JSON object.
var object1 = [{"name": "John"}];
var object2 = [{"location": "San Jose"}];
object1.push(object2);
This will simply append object2 in object1:
[{"name":"John"},{"location":"San Jose"}]

Categories