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)
Related
im trying to set values to an object dynamically passing the attribute that i need to set the value, for example. i need to set name for the object so i need to find this property in the object and set value 'new name'. but some property can be nested for example address.city.name so basically what i need to do is find where the property city is and set the new value to it. if i have one level i could do it easily using something like object[attribute] = newValue;
but sometime the property can be in nested object
object[path][attribute] = newValue;
i was able to accomplish this using the function bellow, but i would to know if its possible do this using lodash. I didn't find any function that find the way of the property
onEditDataCallback={(rowData, columnId, newValue) => {
const path = findPath(rowData, columnId);
if (path) {
rowData[path][columnId] = newValue;
} else {
rowData[columnId] = newValue;
}
return {
...rowData
};
}}
const findPath = (ob, key) => {
const path = [];
const keyExists = (obj) => {
if (!obj || (typeof obj !== 'object' && !Array.isArray(obj))) {
return false;
} else if (obj.hasOwnProperty(key)) {
return true;
} else if (Array.isArray(obj)) {
let parentKey = path.length ? path.pop() : '';
for (let i = 0; i < obj.length; i++) {
path.push(`${parentKey}[${i}]`);
const result = keyExists(obj[i], key);
if (result) {
return result;
}
path.pop();
}
} else {
for (const k in obj) {
path.push(k);
const result = keyExists(obj[k], key);
if (result) {
return result;
}
path.pop();
}
}
return false;
};
keyExists(ob);
return path.join('.');
};
this is what im trying to avoid:
onEditDataCallback={(rowData, columnId, newValue) => {
const temporary = rowData;
switch (columnId) {
case 'city': {
temporary.address.city.name = newValue;
break;
}
case 'addressOne': {
temporary.address.addressOne = newValue;
break;
}
case 'postalCode': {
temporary.address.postalCode.key = newValue;
break;
}
default: {
temporary[columnId] = newValue;
}
}
return {
...temporary
};
}}
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);
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);
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
Hi I need to convert the the numeric values of my object to string. But different properties has different transformation rules.
My sample object:
{
name: "Name"
sRatio: 1.45040404
otherMetric: 0.009993
}
I use JSON.stringify to convert my initial object.
let replacemet = {}
JSON.stringify(metrics[0], function (key, value) {
//Iterate over keys
for (let k in value) {
if ((k !== "sRatio") || (k !== "name")) {
replacemet[k] = (100*value[k]).toFixed(2) + "%"
} else {
if( k === "name") {
replacemet[k] = "yo!"+value[k]
} else{
replacemet[k] = value[k].toFixed(2)
}
}
}
})
But my conditions are not triggered and all properties are converting on the same manner.
The job of the replacer callback is not to fill in some global replacemet object but rather to return a new value.
I think you are looking for something along the lines of
JSON.stringify(sample, function (key, value) {
if (key == "sRatio") {
return value.toFixed(2);
} else if (key == "name") {
return "yo!"+value;
} else if (typeof value == "number") {
return (100*value).toFixed(2) + "%"
} else {
return value;
}
})
Try using switch block that will be really good for this. Detailed description on switch.
let replacemet = {}
JSON.stringify(metrics[0], function (key, value) {
//Iterate over keys
for (let k in value) {
switch(k) {
case "name":
replacemet[k] = "yo!"+value[k];
break;
case "sRatio":
replacemet[k] = value[k].toFixed(2);
break;
default:
replacemet[k] = value[k].toFixed(2);
}
}
})
Hope to help you . I add when dynamic property
metrics =
[
{
name: "Name",
sRatio: 1.45040404,
otherMetric:0.009993
},
{
name: "Name1",
sRatio: 2.45040404,
otherMetric: 1.009993
}
]
;
let source = JSON.stringify(metrics);
let arrJson = new Array();
//arrJson = {};
metrics.forEach(function(value){
let replacemet = {};
for(var k in value) {
if( k.toString().trim() == "name") {
replacemet[k] = "yo!"+value[k] ;
}
else
if ( ( k.toString().trim() !== "sRatio") && ( k.toString().trim() !== "name")) {
replacemet[k] = (100* value[k] ).toFixed(2).toString() + "%" ;
} else {
replacemet[k] = value[k].toFixed(2) ;
}
}
arrJson.push(JSON.stringify(replacemet)) ;
});
console.log(arrJson);