How can I replace all keys of nested object in javascript - javascript

function renameKeys(obj, newKeys) {
const keyValues = Object.keys(obj).map((key) => {
let newKey = key + "1";
if (Array.isArray(obj[key]) == false) {
renameKeys(obj[key], newKeys);
}
console.log(newKey, "]", obj[key]);
return {
[newKey]: obj[key],
};
});
return Object.assign({}, ...keyValues);
}
test = JSON.parse(
'{"verifying_explanation":
{"bus_stop":["1234"],
"elementary_school":["1234"],
"middle_school":["1234"],
"high_school":["1234"]
}
}'
);
console.log(test);
data = renameKeys(test, this);
console.log(data);
It look like all keys changed in function, but it is not applied . I think because of copy principal.
I have no idea how I can manipulate for keys.
I want to replace all keys so that I apply i18n in my code.
So new key will be somethign like
let newKey = i18n.$t(key);
This short code is just for test code.
Please give me some ideas to solve this problem.

You need to define your function to create new key value pairs and then form an object from these. Also, check if the value is an object, to recursively rename nested objects -
function renameKeys(obj) {
const keyValues = Object.entries(obj).map(([key, value]) => {
let newKey = key + "1";
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
value = renameKeys(value);
}
return [newKey, value];
});
return Object.fromEntries(keyValues);
}
test = JSON.parse(
'{"verifying_explanation": {"bus_stop": ["1234"],"elementary_school": ["1234"],"middle_school": ["1234"],"high_school": ["1234"]}}'
);
console.log(test);
data = renameKeys(test, this);
console.log(data);

You can't return new key-value pair in your function, instead of that, you just need to add new key to obj and delete old one.
function renameKeys(obj, newKeys) {
Object.keys(obj).map((key) => {
let newKey = key + "1";
if (Array.isArray(obj[key]) == false) {
renameKeys(obj[key], newKeys);
}
// console.log(newKey, "]", obj[key]);
obj[newKey]=obj[key];
delete obj[key];
});
}
test = JSON.parse(
`{"verifying_explanation":
{"bus_stop":["1234"],
"elementary_school":["1234"],
"middle_school":["1234"],
"high_school":["1234"]
}
}`
);
console.log(test);
data = renameKeys(test, this);
console.log(test);

Related

A way to convert an object with keys of . seperated strings into a JSON object

I'm trying to figure out a way to turn and object like this :
{ "test.subtest.pass" : "test passed", "test.subtest.fail" : "test failed" }
into JSON like this:
{ "test": { "subtest": { "pass": "test passed", "fail": "test failed" }}}
sometimes there may be duplicate keys, as above perhaps there would be another entry like "test.subtest.pass.mark"
I have tried using the following method and it works but it's incredibly ugly:
convertToJSONFormat() {
const objectToTranslate = require('<linkToFile>');
const resultMap = this.objectMap(objectToTranslate, (item: string) => item.split('.'));
let newMap:any = {};
for (const [key,value] of Object.entries(resultMap)) {
let previousValue = null;
// #ts-ignore
for (const item of value) {
// #ts-ignore
if (value.length === 1) {
if(!newMap.hasOwnProperty(item)) {
newMap[item] = key
} // #ts-ignore
} else if (item === value[value.length - 1]) {
if(typeof previousValue[item] === 'string' ) {
const newKey = previousValue[item].toLowerCase().replace(/\s/g, '');;
const newValue = previousValue[item];
previousValue[item] = {};
previousValue[item][newKey] = newValue;
previousValue[item][item] = key;
} else {
previousValue[item] = key;
}
} else if (previousValue === null) {
if (!newMap.hasOwnProperty(item)) {
newMap[item] = {};
}
previousValue = newMap[item];
} else {
if (!previousValue.hasOwnProperty(item)) {
previousValue[item] = {}
previousValue = previousValue[item];
} else if (typeof previousValue[item] === 'string') {
const newValue = previousValue[item];
previousValue[item] = {};
previousValue[item][item] = newValue;
} else {
previousValue = previousValue[item];
}
}
}
}
return newMap;
}
We can utilize recursion to make the code a little less verbose:
function convertToJSONFormat(objectToTranslate) {
// create root object for the conversion result
const result = {};
// iterate each key-value pair on the object to be converted
Object
.entries(objectToTranslate)
.forEach(([path, value]) => {
// utilize a recursive function to write the value into the result object
addArrayPathToObject(result, path.split("."), value);
});
return result;
}
function addArrayPathToObject(root, parts, value) {
const p = parts.shift();
// base-case: We attach the value if we reach the last path fragment
if (parts.length == 0) {
root[p] = value
return;
}
// general case: check if root[p] exists, otherwise create it and set as new root.
if(!root[p]) root[p] = {};
addArrayPathToObject(root[p], parts, value)
}
This function utilizes the fact that objects are pass-by-reference to recursively traverse through the object starting at its root until setting the desired value.
You can add error-handling and other such concerns as necessary for your use.
#Meggan Naude, toJson function copies json object to reference obj for provided keys and value.
const p = { "test.subtest.pass" : "test passed", "test.subtest.fail" : "test failed" };
const result = {} ;
const toJson = (obj, keys, value) => {
if (keys?.length === 1) {
obj[keys[0]] = value;
return obj
} else {
const k = keys.splice(0, 1)
if (k in obj) {
toJson(obj[k], keys, value)
} else {
obj[k] = {};
toJson(obj[k], keys, value)
}
return obj
}
}
Object.keys(p).forEach(key => toJson(result, key.split('.'), p[key]))
console.log(result);

JSON - how to get a "path" to object

In my React project I have a nested JSON and I want to get a key to the object as a string:
Assuming I have a JSON of
{
"section_1": {
"sub_1": {
"object_1": {
"property_1": {},
"property_2": {}
}
}
}
I want to import that JSON as a module and use nice autocompletion to select keys, but if I pass in
section_1.sub_1.object_1 I want to have "section_1.sub_1.object_1" as an output.
Using Object.keys() is not the answer, because
Object.keys(section_1.sub_1.object_1) will give me ["property_1","property_2"]
Example:
import paths from './paths.json'
...
<MyComponent data-path={jsonObjectNameFunction(section_1.sub_1.object_1)} />
...
I want data-path="section_1.sub_1.object_1"
You'll need to pass in not just section_1.sub_1.object_1 but also the object to look within (let's call it obj), like this;
const obj = /*the import resulting in:*/{
"section_1": {
"sub_1": {
"object_1": {
"property_1": {},
"property_2": {}
}
}
};
someFunction(obj, obj.section_1.sub_1.object_1);
To implement someFunction, we have to find the name/value pairs at each level that lead go obj, something like this:
function someFunction(container, target, path = "") {
for (const [key, value] of Object.entries(container)) {
const possiblePath = path ? path + "." + key : key;
if (value === target) {
return possiblePath;
}
if (value && typeof value === "object") {
const found = someFunction(value, target, possiblePath);
if (found) {
return found;
}
}
}
return null;
}
Live Example:
"use strict";
const obj = /*the import resulting in:*/{
"section_1": {
"sub_1": {
"object_1": {
"property_1": {},
"property_2": {}
}
}
}
};
console.log(someFunction(obj, obj.section_1.sub_1.object_1));
function someFunction(container, target, path = "") {
for (const [key, value] of Object.entries(container)) {
const possiblePath = path ? path + "." + key : key;
if (value === target) {
return possiblePath;
}
if (value && typeof value === "object") {
const found = someFunction(value, target, possiblePath);
if (found) {
return found;
}
}
}
return null;
}
I understand u want to get value from object base on path.
U can use lodash get value by path

JSON.stringify replacer does not replace values

Why does the replacer not replace the datetime values? Console output is right.
let replacer = (key, value) => {
// console.log("key", key);
if (value === null) {
return '';
} else {
if (key === 'datetime') {
console.log('key', key, value);
return formatDate(value, 'short', 'de');
} else {
return value;
}
}
};
const header = Object.keys(items[0]);
let csv = items.map(row =>
header.map(fieldName =>
JSON.stringify(
row[fieldName],
replacer(fieldName, row[fieldName])
)
).join(','));
I guess it's because you provide replacer(fieldName, row[fieldName]) as a replacer argument, which returns a value. Try to provide it a function (instead of a function call)

Swap javascript object index by name

My javascript object looks like the example below, I am wondering how I should write a swap function to change the element position in the object. For example, I want to swap two elements from position 1 to 2 and 2 to 1.
{
element_name_1 : {
//.. data
}
element_name_2 : {
//.. data
}
element_name_3 : {
//.. data
}
element_name_4 : {
//.. data
}
}
Now I want to swap element_name_2 with element_name_1.
As Miles points out, your code is probably broken and should use an array. I wouldn't use it, nor is it tested, but it is possible.
var data = {
element_name_1: {},
element_name_2: {},
element_name_3: {},
element_name_4: {}
}
console.log(data);
var swap = function(object, key1, key2) {
// Get index of the properties
var pos1 = Object.keys(object).findIndex(x => {
return x === key1
});
var pos2 = Object.keys(object).findIndex(x => {
return x === key2
});
// Create new object linearly with the properties swapped
var newObject = {};
Object.keys(data).forEach((key, idx) => {
if (idx === pos1)
newObject[key2] = object[key2];
else if (idx === pos2)
newObject[key1] = object[key1];
else
newObject[key] = object[key];
});
return newObject;
}
console.log(swap(data, "element_name_1", "element_name_2"));
Have a look at the code, may this solve the problem
function swapFunction(source, destination) {
var tempValu,
sourceIndex;
for ( i = 0; i < Arry.length; i++) {
for (var key in Arry[i]) {
Ti.API.info('key : ' + key);
if (source == key) {
tempValu = Arry[i];
sourceIndex = i;
}
if (destination == key) {
Arry[sourceIndex] = Arry[i];
Arry[i] = tempValu;
return Arry;
}
}
}
}
JSON.stringify(swapFunction("key_1", "key_3")); // [{"key_3":"value_3"},{"key_2":"value_2"},{"key_1":"value_1"},{"key_4":"value_4"},{"key_5":"value_5"}]
Let me know if this works.
Good Luck & Cheers
Ashish Sebastian

Javascript changing object properties

I have an object and I am iterating through it's properties in order to change them (I want to replace 'a.1'-kind to 'a[1]'-kind):
.fail(function (data) {
var errors = data.responseJSON;
console.log("Object before: ", errors);
console.log("Changed properties:")
for (var property in errors) {
if (errors.hasOwnProperty(property)) {
if (property.includes('.')) {
property = property.replace(/\./, "[");
property = property.replace(/$/, "]");
console.log(property);
}
}
}
console.log("Object after: ", errors);
The properties change during iteration, but object's properties don't change for real:
How do I changed object's properties not only while iterating through them, but "forever"?:)
Appreciate any help:)
You may delete and reassign:
if (property.includes('.')) {
errors[property.replace(/\./, "[").replace(/$/, "]")]=errors[property];
delete errors[property];
}
You may ask why does
property=property.replace(..);
Not work?
Well property is not related to object in any way. Its just a string...
Like the post from #Jonas w above, you can do a delete and reassign the value.
Another example here (does not include your string replacement/regex logic, but shows how you can update/alter the keys:
let logger = document.querySelector('pre');
let obj = {
foo: 'foo-value',
bar: 'foo-value',
baz: 'foo-value',
qux: 'foo-value'
};
logger.innerHTML = `Original: ${JSON.stringify(obj, null, 2)}\n`;
Object.keys(obj).forEach((oldKey) => {
let newKey = oldKey + '-new';
let originalVal = obj[oldKey];
obj[newKey] = originalVal;
delete obj[oldKey];
});
logger.innerHTML += `Updated: ${JSON.stringify(obj, null, 2)}\n`;
<pre></pre>
A functional approach:
function replaceProperties(obj) {
var newObj = Object.getOwnPropertyNames(obj).reduce(function (newObj, prop) {
var newProp = prop;
if (prop.includes('.')) {
newProp = prop.replace(/\./, "[").replace(/$/, "]");
}
newObj[newProp] = obj[prop];
return newObj;
}, {});
return newObj;
}
var newObj = replaceProperties(errors);

Categories