I have a set of object of object. For example
{
"123":{
id:123,
name:"abc"
},
"456":{
id:456,
name:"def"
},
"789":{
id:789,
name:"ghi"
}
}
I would like to know how to loop over my object and check if the value "def" exist in the object list?
Can I know how to loop through every iteration and only do decision ?? For example first iteration is abc then next is def then next is ghi . because abc and def is not same but when come to def and def it is same .Can I do action or logic after finish loop through every iteration ?
Use a for loop on the object to check that value exist in name property or not:
var obj = {
123: {
id: 123,
name: 'abc'
},
456: {
id: 456,
name: 'def'
},
789: {
id: 789,
name: 'ghi'
}
};
var checkVal = 'def';
let match = false;
for(var objKey in obj) {
if(obj[objKey].name === checkVal) {
match = true;
}
}
console.log('found ', match);
There are a couple of ways to loop through an object in Javascript, depending on what version you are using.
The basics of it Ankit talked about in his answer:
const search = {
"123":{
id:123,
name:"abc"
},
"456":{
id:456,
name:"def"
},
"789":{
id:789,
name:"ghi"
}
};
for(let key in search) {
if(search[key].name == 'def') {
console.log(search[key]);
}
}
If you are using a newer version of Javascript, you can do the following:
const search = {
"123":{
id:123,
name:"abc"
},
"456":{
id:456,
name:"def"
},
"789":{
id:789,
name:"ghi"
}
}
for(let obj of Object.values(search)){
if(obj.name==='def') console.log(obj);
}
// or, very similarly
for(let key of Object.keys(search)) {
let obj = search[key];
if(obj.name=='def') console.log(obj);
}
Or, lastly.
const search = {
"123":{
id:123,
name:"abc"
},
"456":{
id:456,
name:"def"
},
"789":{
id:789,
name:"ghi"
}
}
for(let [key, obj] of Object.entries(search)){
if(obj.name=='def') console.log('found on key ', key, 'value:', obj);
}
Note that the last one uses the destructuring assignment so that you do not need to use a placeholder variable simply to assign key and object/value out inside the loop.
Related
I am trying to aggregate the same key values into an array by value.
so for example I have an array of objects, like so
const data = [{foo: true},{foo: false},{bar: true},{buzz: false}]
when they get aggregated the array transforms into
[
foo: {true: [{foo: true}], false: [{foo: false}]},
bar: {true: [{bar: true}]},
buzz: {false: [{buzz: false}]}
]
the array entries is the original object.
Now I know the keys that I want to group by..
they are foo, bar, buzz and fizz.
But fizz is not part of the original array, so the return is undefined, like so
[
foo: {true:[{foo: true}], false: [{foo: false}]},
bar: {true: [{bar: true}]},
buzz: {false: A[{buzz: false}]}
fizz: {undefined: [{foo: true},{foo: false},{bar: true},{buzz: false}]}
],
how do I reduce the original array without including the fizz value that is undefined?
code here:
let v = [];
let types = ['foo', 'bar', 'buzz', 'fizz' ]
for (let x = 0; x < types.length; x++) {
let data = data.reduce((acc, i) => {
if (!acc[i[types[x]]]) {
acc[i[types[x]]] = [i]
}
else if (Array.isArray(acc[i[types[x]]])) {
acc[i[types[x]]].push(i);
}
else if (typeof acc[i[types[x]]] === 'object') {
acc[i[types[x]]] = [acc[i[types[x]]]]
acc[i[types[x]]].push(i)
}
return acc;
}, {})
v.push({ [types[x]]: data });
}
return v;
You were close, you just need to check if the property you were adding was undefined before adding. You can also check if the reduced object has any properties before adding to the result object.
Note that this may not be the most efficient way of doing it, but sometimes it's better to understand the code than it is to have highly efficient code.
const data = [{
foo: true
}, {
foo: false
}, {
bar: true
}, {
buzz: false
}];
let v = [];
let types = ['foo', 'bar', 'buzz', 'fizz']
for (let x = 0; x < types.length; x++) {
let reduced = data.reduce((acc, i) => {
// /* Added this type check */
if (!acc[i[types[x]]] && typeof i[types[x]] !== 'undefined') {
acc[i[types[x]]] = [i]
} else if (Array.isArray(acc[i[types[x]]])) {
acc[i[types[x]]].push(i);
} else if (typeof acc[i[types[x]]] === 'object') {
acc[i[types[x]]] = [acc[i[types[x]]]]
acc[i[types[x]]].push(i)
}
return acc;
}, {});
// Doesn't add a property for the type if there are no data
if (Object.keys(reduced).length) {
v.push({
[types[x]]: reduced
});
}
}
console.log(v);
Have a look at how Array.prototype.reduce works. It might be the right method to build your approach upon.
A generic way of solving the OP's problem was to iterate the provided data array. For each item one would extract its key and value. In case the item's key is listed (included) in another provided types array, one would continue creating a new data structure and collecting the currently processed item within the latter.
One does not want to iterate the types array for it will cause a unnecessarily complex lookup for the data items, each time a type item is going to be processed.
Thus a generically working (better code reuse) reduce method might be the best solution to the OP's problem ...
const sampleDataList = [
{ foo: true },
{ foo: false },
{ bar: true },
{ baz: false },
{ buzz: false },
{ baz: false },
{ bar: true }
];
// foo: {true: [{foo: true}], false: [{foo: false}]},
// bar: {true: [{bar: true}]},
// buzz: {false: [{buzz: false}]}
function collectItemIntoInclusiveKeyValueGroup(collector, item) {
const { inclusiveKeyList, index } = collector;
const firstItemEntry = Object.entries(item)[0];
const key = firstItemEntry[0];
const isProceedCollecting = ( // proceed with collecting ...
//
!Array.isArray(inclusiveKeyList) // - either for no given list
|| inclusiveKeyList.includes(key) // - or if item key is listed.
);
if (isProceedCollecting) {
let keyGroup = index[key]; // access the group identified
if (!keyGroup) { // by an item's key, ... or ...
// ...create it in case ...
keyGroup = index[key] = {}; // ...it did not yet exist.
}
const valueLabel = String(firstItemEntry[1]); // item value as key.
let valueGroupList = keyGroup[valueLabel]; // acces the group list
if (!valueGroupList) { // identified by an item's
// value, ...or create it in
valueGroupList = keyGroup[valueLabel] = []; // case it did not yet exist.
}
// push original reference into a grouped
// key value list, as required by the OP.
valueGroupList.push(item);
}
return collector;
}
console.log(
"'foo', 'bar', 'buzz' and 'fizz' only :",
sampleDataList.reduce(collectItemIntoInclusiveKeyValueGroup, {
inclusiveKeyList: ['foo', 'bar', 'buzz', 'fizz'],
index: {}
}).index
);
console.log(
"'foo', 'bar' and 'baz' only :",
sampleDataList.reduce(collectItemIntoInclusiveKeyValueGroup, {
inclusiveKeyList: ['foo', 'bar', 'baz'],
index: {}
}).index
);
console.log(
"all available keys :",
sampleDataList.reduce(collectItemIntoInclusiveKeyValueGroup, {
index: {}
}).index
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Try something like:
const data = [{foo: true},{foo: false},{bar: true},{buzz: false}];
let v = [];
let types = ['foo', 'bar', 'buzz', 'fizz' ];
for (let x = 0; x < types.length; x++) {
let filteredlist = data.filter(function (d) {
return Object.keys(d)[0] == types[x];
});
let isTrue = 0;
let isFalse = 0;
if (filteredlist.length > 0) {
for (let i = 0; i < filteredlist.length; i++) {
let trueOrfalse = eval("filteredlist[i]." + types[x]);
if (trueOrfalse) {
isTrue++;
} else {
isFalse++;
}
}
v.push(types[x], {true: isTrue, false: isFalse});
}
}
console.log(v);
Assuming you only want to count the number of each key (e.g. true or false) you can use the following code.
I've written this as a function named 'aggregate' so that it can be called multiple times with different arguments.
const initialData = [{foo: true},{foo: true},{foo: false},{bar: true},{buzz: false}];
const types = ['foo', 'bar', 'buzz', 'fizz'];
const aggregate = (data, types) => {
const result = {};
data.forEach(item => {
// Extract key & value from object
// Note: use index 0 because each object in your example only has a single key
const [key, value] = Object.entries(item)[0];
// Check if result already contains this key
if (result[key]) {
if (result[key][value]) {
// If value already exists, append one
result[key][value]++;
} else {
// Create new key and instantiate with value 1
result[key][value] = 1;
}
} else {
// If result doesn't contain key, instantiate with value 1
result[key] = { [value]: 1 };
}
});
return result;
};
console.log(aggregate(initialData, types));
This will output the following (note I've added another {foo: true} to your initialData array for testing).
The output should also be an object (not array) so that each key directly relates to its corresponding value, as opposed to an Array which will simply place the value as the next item in the Array (without explicitly linking the two).
{
foo: { true: 2, false: 1 },
bar: { true: 1 },
buzz: { false: 1 }
}
This is an object to be processed:
var q = {
email: {contains: "noname#hotmail.com"},
name: {contains: "someuser"}
};
I would like to go through each key of q and if the corresponding value is an object that has the property contains then replace it with $regex.
Related information can be found here: JavaScript: Object Rename Key
You can try the following way:
var q = {
email: {contains: "noname#hotmail.com"},
name: {contains: "someuser"}
};
for(var k in q){
if(q[k].hasOwnProperty('contains')){
Object.defineProperty(q[k], '$regex',
Object.getOwnPropertyDescriptor(q[k], 'contains'));
delete q[k]['contains'];
}
}
console.log(q);
for(const obj of Object.values(q)) {
obj.$regex = obj.contains;
delete obj.contains;
}
Just go over all values inside q and copy the contains property into the $regex property.
To iterate over object keys first you have to fetch them, here is one simple approach
const keys = Object.keys(q); // ["email", "name"]
Now iterate over the array which we got and perform regex testing;
keys.forEach(key => {
let value = q[key].contains;
// create $regex and assign value
// remove .contains
})
You can loop through the objects and first put current value of contains property in $regex and then delete the contains property.
Below is working code:
var q = {
email: {
contains: "noname#hotmail.com"
},
name: {
contains: "someuser"
}
};
for (var i of Object.values(q)) {
if (i.hasOwnProperty("contains")) {
i.$regex = i.contains;
delete i.contains;
}
}
console.log(q);
var q = {
email: {contains: "noname#hotmail.com"},
name: {contains: "someuser"}
};
Object.keys(q).forEach(k => {
if (typeof q[k].contains != 'undefined'){
q[k].$regex = q[k].contains;
delete q[k].contains;
}
})
console.log(q);
Other version using Es 6 features
const renameProp = (
oldProp,
newProp,
{ [oldProp]: old, ...others }
) => {
return {
[newProp]: old,
...others
};
};
let q = {
email: {contains: "noname#hotmail.com"},
name: {contains: "someuser"}
};
let newObj = {}
for (let propName in q) {
newObj[propName] = renameProp("contains","$regex",q[propName])
}
console.log(newObj)
var q = {
email: {
contains: "noname#hotmail.com"
},
name: {
contains: "someuser"
},
asdf: "asdf"
};
Object.keys(q).forEach(function(item, index) {
if (typeof q[item] == "object" && q[item].contains) {
q[item].$regex = q[item].contains;
delete q[item].contains;
}
})
I have object in this structure:
obj = {
user: { name: 'jeterson' },
title: 'I am a test'
}
I have one key with value: user.name.
I have trying get value like this: obj[key], meaning obj['user.name']. It not works, only works for obj.title.
My object have many values that are also objects, and i want get value like this:
myobject[mykey]
It is possible get value from property object like above ?
You can access it with:
obj['user']['name']
Or alternatively:
obj.user.name
If you want to get from a key like "user.name" to the value, you woulr have to do some logic yourself. You could hack something together like this:
let obj = {
user: {
name: 'jeterson'
},
title: 'I am a test'
}
let key = 'user.name';
let keys = key.split('.');
let res = obj;
while (keys.length > 0 && res) {
let k = keys.shift();
res = res[k];
}
console.log(res) // "jeterson"
When the keys do not match, res holds undefined.
You've got multiple solutions to access an element of an object with its keys:
var obj = {
user: { name: 'jeterson' },
title: 'I am a test'
}
console.log(obj['user']['name']);
console.log(obj['user'].name);
console.log(obj.user['name']);
console.log(obj.user.name);
But you can't do it easily with a variable key = 'user.name'.
If you need to use a variable containing the nested-keys, you could create a function.
Updated answer: An amazingly short way to achieve it is to use .reduce():
// My function
function obj_tree_key(obj, path) {
return path.split('.').reduce((accu, val) => accu[val] || 'Not found', obj);
}
var obj1 = {
user: {
name: 'jeterson'
},
title: 'I am a test'
}
console.log(obj_tree_key(obj1, 'user.name')); // Outputs "jeterson"
// Here is an example with error:
var obj2 = {
user: {
nameeeee: 'jeterson'
},
title: 'I am a test'
}
console.log(obj_tree_key(obj2, 'user.name'));
Old answer: Use a for to loop through the keys and reduce the oject:
// My function
function obj_tree_key(obj, tree_key) {
var result = obj;
var keys = tree_key.split('.');
for (var i = 0; i < keys.length; i++) {
result = result[keys[i]] || 'Not found'; // Error handling
}
return result;
}
var obj1 = {
user: {
name: 'jeterson'
},
title: 'I am a test'
}
console.log(obj_tree_key(obj1, 'user.name')); // Outputs "jeterson"
// Here is an example with error:
var obj2 = {
user: {
nameeeee: 'jeterson'
},
title: 'I am a test'
}
console.log(obj_tree_key(obj2, 'user.name'));
Hope it helps.
first get the user, then the name:
obj['user']['name']
or
obj.user.name
You can also use
obj.user.name
You could access it using
console.log(obj.user.name);
You can do it in 2 way:
obj['user']['name']
or
obj.user.name
I'm currently learning JavaScript and my teacher asked me to do an exercise that would return an array with all the names of this object:
{
name: 'grandma',
daughter: {
name: 'mother',
daughter: {
name: 'daughter',
daughter: {
name: 'granddaughter'
}
}
}
}
my question is similar to this one but the solution does not work for me because my object does not contain any arrays. The code I have so far:
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value));
}
else {
result.push(value);
}
}
return result;
}
function nameMatrioska(target) {
return toArray(target);
}
which prints out this : [ 'grandma', [ 'mother', [ 'daughter', [Array] ] ] ]
but what my teacher wants is: ['grandma', 'mother', 'daughter', 'granddaughter']
codepen
Obviously you push an array to an array, where all nested children appears as an array.
To solve this problem, you could iterate the array and push only single items to the result set.
A different method is, to use some built-in techniques, which works with an array, and returns a single array without a nested array.
Some methods:
Array#concat, creates a new array. It works with older Javascript versions as well.
result = result.concat(toArray(value));
Array#push with an array and Function#apply for taking an array as parameter list. It works in situ and with older versions of JS.
Array.prototype.push.apply(result, toArray(value));
[].push.apply(result, toArray(value)); // needs extra empty array
Spread syntax ... for spreading an array as parameters. ES6
result.push(...toArray(value));
Spread syntax is a powerful replacement for apply with a greater use. Please the the examples as well.
Finally an example with spread syntax.
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (value && typeof value === 'object') { // exclude null
result.push(...toArray(value));
// ^^^ spread the array
}
else {
result.push(value);
}
}
return result;
}
function nameMatrioska(target) {
return toArray(target);
}
var object = { name: 'grandma', daughter: { name: 'mother', daughter: { name: 'daughter', daughter: { name: 'granddaughter' } } } };
console.log(nameMatrioska(object));
You need .concat instead of .push. Push adds one item to an array; concat joins two arrays together.
['grandmother'].concat(['mother', 'daughter'])
-> ['grandmother', 'mother', 'daughter']
Unlike push, which modifies the array you call it on, concat creates a new array.
var a1 = [ 'grandmother' ];
a1.push( 'mother' );
console.log( a1 );
-> ['grandmother', 'mother']
var a2 = [ 'steve' ];
var result = a2.concat(['Jesus', 'Pedro']);
console.log( a1 );
-> ['steve']
console.log( result );
-> ['steve', 'Jesus', 'Pedro']
Try this
function toArray(obj) {
var result = "";
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result = result.concat(" " + toArray(value));
}
else {
result = result.concat(value);
}
}
return result;
}
function nameMatrioska(target) {
return toArray(target).split(" ");
}
function toArray(obj) {
var result = [];
for (var prop in obj) {
var value = obj[prop];
if (typeof value === 'object') {
result = result.concat(toArray(value))
} else {
result.push(value);
}
}
return result;
}
function nameMatrioska(target) {
return toArray(target);
}
//USER
var names = {
name: 'grandma',
daughter: {
name: 'mother',
daughter: {
name: 'daughter',
daughter: {
name: 'granddaughter'
}
}
}
};
console.log(nameMatrioska(names));
//Output: ["grandma", "mother", "daughter", "granddaughter"]
You are really close.
You have to flatten your array in your last step.
Tip: In general be careful when checking for type object because e.g. null, undefined are also objects in JavaScript world!
function isObject(value) {
if(value === undefined) return "Undefined";
if(value === null) return "Null";
const string = Object.prototype.toString.call(value);
return string.slice(8, -1);
}
function collectPropertiesRec(object, propertyName) {
const result = [ ];
for(const currentPropertyName in object) {
const value = object[currentPropertyName];
if(isObject(value) === 'Object') {
result.push(collectPropertiesRec(value, propertyName));
}
else if(currentPropertyName === propertyName) {
result.push(value);
}
}
return result;
}
function flattenDeep(arr1) {
return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), [ ]);
}
//USER
const names = {
name: 'grandma',
daughter: {
name: 'mother',
daughter: {
name: 'daughter',
daughter: {
name: 'granddaughter'
}
}
}
};
var result = collectPropertiesRec(names, "name");
alert(flattenDeep(result).join(", "));
I have an array of objects that can be of any length and any depth. I need to be able to find an object by its id and then modify that object within the array. Is there an efficient way to do this with either lodash or pure js?
I thought I could create an array of indexes that led to the object but constructing the expression to access the object with these indexes seems overly complex / unnecessary
edit1; thanks for all yours replies I will try and be more specific. i am currently finding the location of the object I am trying to modify like so. parents is an array of ids for each parent the target object has. ancestors might be a better name for this array. costCenters is the array of objects that contains the object I want to modify. this function recurses and returns an array of indexes that lead to the object I want to modify
var findAncestorsIdxs = function(parents, costCenters, startingIdx, parentsIdxs) {
var idx = startingIdx ? startingIdx : 0;
var pidx = parentsIdxs ? parentsIdxs : [];
_.each(costCenters, function(cc, ccIdx) {
if(cc.id === parents[idx]) {
console.log(pidx);
idx = idx + 1;
pidx.push(ccIdx);
console.log(pidx);
pidx = findAncestorsIdx(parents, costCenters[ccIdx].children, idx, pidx);
}
});
return pidx;
};
Now with this array of indexes how do I target and modify the exact object I want? I have tried this where ancestors is the array of indexes, costCenters is the array with the object to be modified and parent is the new value to be assigned to the target object
var setParentThroughAncestors = function(ancestors, costCenters, parent) {
var ccs = costCenters;
var depth = ancestors.length;
var ancestor = costCenters[ancestors[0]];
for(i = 1; i < depth; i++) {
ancestor = ancestor.children[ancestors[i]];
}
ancestor = parent;
console.log(ccs);
return ccs;
};
this is obviously just returning the unmodified costCenters array so the only other way I can see to target that object is to construct the expression like myObjects[idx1].children[2].grandchildren[3].ggranchildren[4].something = newValue. is that the only way? if so what is the best way to do that?
You can use JSON.stringify for this. It provides a callback for each visited key/value pair (at any depth), with the ability to skip or replace.
The function below returns a function which searches for objects with the specified ID and invokes the specified transform callback on them:
function scan(id, transform) {
return function(obj) {
return JSON.parse(JSON.stringify(obj, function(key, value) {
if (typeof value === 'object' && value !== null && value.id === id) {
return transform(value);
} else {
return value;
}
}));
}
If as the problem is stated, you have an array of objects, and a parallel array of ids in each object whose containing objects are to be modified, and an array of transformation functions, then it's just a matter of wrapping the above as
for (i = 0; i < objects.length; i++) {
scan(ids[i], transforms[i])(objects[i]);
}
Due to restrictions on JSON.stringify, this approach will fail if there are circular references in the object, and omit functions, regexps, and symbol-keyed properties if you care.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_native_JSON#The_replacer_parameter for more info.
As Felix Kling said, you can iterate recursively over all objects.
// Overly-complex array
var myArray = {
keyOne: {},
keyTwo: {
myId: {a: '3'}
}
};
var searchId = 'myId', // Your search key
foundValue, // Populated with the searched object
found = false; // Internal flag for iterate()
// Recursive function searching through array
function iterate(haystack) {
if (typeof haystack !== 'object' || haystack === null) return; // type-safety
if (typeof haystack[searchId] !== 'undefined') {
found = true;
foundValue = haystack[searchId];
return;
} else {
for (var i in haystack) {
// avoid circular reference infinite loop & skip inherited properties
if (haystack===haystack[i] || !haystack.hasOwnProperty(i)) continue;
iterate(haystack[i]);
if (found === true) return;
}
}
}
// USAGE / RESULT
iterate(myArray);
console.log(foundValue); // {a: '3'}
foundValue.b = 4; // Updating foundValue also updates myArray
console.log(myArray.keyTwo.myId); // {a: '3', b: 4}
All JS object assignations are passed as reference in JS. See this for a complete tutorial on objects :)
Edit: Thanks #torazaburo for suggestions for a better code.
If each object has property with the same name that stores other nested objects, you can use: https://github.com/dominik791/obj-traverse
findAndModifyFirst() method should solve your problem. The first parameter is a root object, not array, so you should create it at first:
var rootObj = {
name: 'rootObject',
children: [
{
'name': 'child1',
children: [ ... ]
},
{
'name': 'child2',
children: [ ... ]
}
]
};
Then use findAndModifyFirst() method:
findAndModifyFirst(rootObj, 'children', { id: 1 }, replacementObject)
replacementObject is whatever object that should replace the object that has id equal to 1.
You can try it using demo app:
https://dominik791.github.io/obj-traverse-demo/
Here's an example that extensively uses lodash. It enables you to transform a deeply nested value based on its key or its value.
const _ = require("lodash")
const flattenKeys = (obj, path = []) => (!_.isObject(obj) ? { [path.join('.')]: obj } : _.reduce(obj, (cum, next, key) => _.merge(cum, flattenKeys(next, [...path, key])), {}));
const registrations = [{
key: "123",
responses:
{
category: 'first',
},
}]
function jsonTransform (json, conditionFn, modifyFn) {
// transform { responses: { category: 'first' } } to { 'responses.category': 'first' }
const flattenedKeys = Object.keys(flattenKeys(json));
// Easily iterate over the flat json
for(let i = 0; i < flattenedKeys.length; i++) {
const key = flattenedKeys[i];
const value = _.get(json, key)
// Did the condition match the one we passed?
if(conditionFn(key, value)) {
// Replace the value to the new one
_.set(json, key, modifyFn(key, value))
}
}
return json
}
// Let's transform all 'first' values to 'FIRST'
const modifiedCategory = jsonTransform(registrations, (key, value) => value === "first", (key, value) => value = value.toUpperCase())
console.log('modifiedCategory --', modifiedCategory)
// Outputs: modifiedCategory -- [ { key: '123', responses: { category: 'FIRST' } } ]
I needed to modify deeply nested objects too, and found no acceptable tool for that purpose. Then I've made this and pushed it to npm.
https://www.npmjs.com/package/find-and
This small [TypeScript-friendly] lib can help with modifying nested objects in a lodash manner. E.g.,
var findAnd = require("find-and");
const data = {
name: 'One',
description: 'Description',
children: [
{
id: 1,
name: 'Two',
},
{
id: 2,
name: 'Three',
},
],
};
findAnd.changeProps(data, { id: 2 }, { name: 'Foo' });
outputs
{
name: 'One',
description: 'Description',
children: [
{
id: 1,
name: 'Two',
},
{
id: 2,
name: 'Foo',
},
],
}
https://runkit.com/embed/bn2hpyfex60e
Hope this could help someone else.
I wrote this code recently to do exactly this, as my backend is rails and wants keys like:
first_name
and my front end is react, so keys are like:
firstName
And these keys are almost always deeply nested:
user: {
firstName: "Bob",
lastName: "Smith",
email: "bob#email.com"
}
Becomes:
user: {
first_name: "Bob",
last_name: "Smith",
email: "bob#email.com"
}
Here is the code
function snakeCase(camelCase) {
return camelCase.replace(/([A-Z])/g, "_$1").toLowerCase()
}
export function snakeCasedObj(obj) {
return Object.keys(obj).reduce(
(acc, key) => ({
...acc,
[snakeCase(key)]: typeof obj[key] === "object" ? snakeCasedObj(obj[key]) : obj[key],
}), {},
);
}
Feel free to change the transform to whatever makes sense for you!