How to construct JSON dynamically from array list of elements? - javascript

I have a list of elements in an array: empIds: [38670, 38671, 38672, 38673]
I am trying to build a JSON that holds all these array elements in the payload:
{
"members": [
{
"EmployeeId": "38670"
},
{
"EmployeeId": "38671"
},
{
"EmployeeId": "38672"
},
{
"EmployeeId": "38673"
}
]
}
I wasn't completely sure as I am trying to get my head around. Below is my incomplete implementation:
`
let parts = [];
for(i=0;i<memberInternalIds.length; i++){
if(memberInternalIds.length == 1){
parts ={participantId: memberInternalIds[0]}
} else {
parts ={participantId: memberInternalIds[i]}
}
}
`
Not sure how to dynamically create JSON structure with followed by comma-separated key/values.

const empIds = [38670, 38671, 38672, 38673];
let payload = { members: empIds.map(id => ({"EmployeeId": id})) };
// Convert the payload to a JSON string
const jsonStr = JSON.stringify(payload);
// Print the JSON string
console.log(jsonStr);

Related

How to loop through objects and count unique values of key?

I have logs of json files which are objects that look like
{
"logs": [
{
"id": "12321321321321",
"email": "test#email.com",
"message": "ahahaha"
},
{
"id": "12321321312",
"email": "test#email.com",
"message": "hahahaha."
},
"id": "12321321321"
}
I need to return a new object that contains
{
"hello_id": outer id of the json file,
"array": [
{
"email": "test#me.com",
"total": 2
}
]
}
So far I am looping through the json files and have
jsonsInDirectory.forEach((file) => {
const fileData = fs.readFileSync(path.join("./logs", file), "utf8");
const jsonData = JSON.parse(fileData);
}
});
The key is "logs" and "id" and the values are the objects in the "logs" and the value of "id"
How can I count and return a new object at the same time?
You can try this approach: make a hash object that counts emails. Then just map it to an array of objects.
const data = {
logs: [{
id: "89004ef9-e825-4547-a83a-c9e9429e8f95",
email: "noah.sanchez#me.com",
message: "successfully handled skipped operation."
},
{
id: "89004ef9-e825-4547-a83a-c9e9429e8f95",
email: "noah.sanchez#me.com",
message: "successfully handled skipped operation."
},
{
id: "89004ef9-e825-4547-a83a-c9e9429e8f95",
email: "noname#me.com",
message: "successfully handled skipped operation."
}],
id: "56f83bed-3705-4115-9067-73930cbecbc0",
};
const emails = data.logs.reduce((acc, { email }) => {
acc[email] = (acc[email] ?? 0) + 1;
return acc;
}, {});
const tally = Object.entries(emails)
.map(([email, total]) => ({ email, total }));
const result = { logs_id: data.id, tally };
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0 }
When you do const jsonData = JSON.parse(fileData);, you get the file data as a JSON and knowing the struct of that JSON you can easily get the info.
I have created a example https://codesandbox.io/s/stackoverflow-logs-count-example-jys2vg?file=/src/index.js
It may not solve exactly wath you want.
To solve this problem with the most time efficiency, you can create a tally object by firstly creating a map of the occurences of each mail with the email as the key and no of occurences as the value, since this will take constant (O(1)) time to execute, afterwhich you can create the tally array from the map as given below
output = []
jsonsInDirectory.forEach((file) => {
const fileData = fs.readFileSync(path.join("./logs", file), "utf8");
const jsonData = JSON.parse(fileData);
var map = {}
jsonData.logs.forEach((log) => {
if(log.email in map){
map[log.email] += 1
}
else {
map[log.email] = 1
}
});
var tally = []
for(var email in map){
tally.push({email: email, total: map[email]})
}
output.push({logs_id: jsonData['id'], tally: tally});
})

Javascript conditionally adding the nested object using map() operator

I have a below JSON,
var original = {
"todos": [
{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [
{
"vpa": "log#bda",
"mccCode": "0000"
}
]
}
]
}
And am trying to add new data inside the nested array i.e., "vpainfo". I have tried using the below code and able to adding the new values inside "vpainfo".
var newdata = {"vpa":"first#bda","mccCode":"1111"};
var newObj =
Object.assign({}, original,
{
todos: original.todos.map(todoInfo=>(todoInfo.accountNo=="50190000")?[
...todoInfo.vpainfo,
newdata
]: todoInfo)
});
And the resulted object is,
{"todos":[[{"vpa":"log#bda","mccCode":"0000"},{"vpa":"first#bda","mccCode":"1111"}]]}
But few of the key and values(accountNo and name) are getting missed, how do we get the full object with the latest updated values?
You only return the array, not the actual object, hence the error.
var original = {
"todos": [
{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [
{
"vpa": "log#bda",
"mccCode": "0000"
}
]
}
]
}
const newdata = {"vpa":"first#bda","mccCode":"1111"};
const newObj = Object.assign({}, original,
{
todos: original.todos.map(todoInfo=>{
if(todoInfo.accountNo=="50190000"){
return {
...todoInfo,
vpainfo: [...todoInfo.vpainfo, newdata]
}
}
return todoInfo
})
});
console.log(newObj)
All those spread operators seem a little excessive...
If all you wanna do is add newdata to that existing array, then do that:
var original = {
"todos": [{
"accountNo": "50190000",
"name": "Sarkar",
"vpainfo": [{
"vpa": "log#bda",
"mccCode": "0000"
}]
}]
};
const newdata = {
"vpa": "first#bda",
"mccCode": "1111"
};
// Find the correct account.
const account = original.todos.filter(t => t.accountNo === '50190000')[0];
if (account) {
account.vpainfo.push(newdata);
}
console.log(original);

How to update the attribute value for dynamic JSON file using node.js

I'm checking if the input.json file key matches in the server.json file then update the value of server.json file. The problem is server.json file is dynamic json file and the structure is not able predicted and it contains 100 elements with nested array and complex format. I just want to check the input.json key is available anywhere in the server.json (dynamic content) file
I have below json input file with some attribute and values:
input.json:
{"country":"GB","currency":"GBP"}
Sample server.json (Dynamic content unpredictable):
{
"bank": [
{
"country":"US",
"currency":"USD"
}
]
}
Output:
{
"bank": [
{
"country":"GB",
"currency":"GBP",
}
]
}
I just want to update the above server.json file values from input.json file if the key matches. And both (Input.json, and server.json ) files should have same key (country,currency).But the problem is the index of key in server.json is unknown, and it will be dynamic content.
User might give any input which is available in the server.json and based on key matching it needs to updated.
Tried below sample:
async function generateRequestBody(actual, index, functionRef) {
let callback;
let payload;
_globaldeclartion = actual;
Object.keys(dataset[index]).forEach(function (queueId) {
if (queueId == functionRef) {
payload = dataset[index][queueId];
return;
}
});
payload = await jsonValidator(payload);
await updateJsonFile(_globaldeclartion, async (data) => {
Object.keys(data).forEach(async (T) => {
console.log(T);
data[T] = payload[T];
});
callback = data;
return data;
});
return callback;
I just want to update the server.json if the input.json file key matches with server.json (un predictable json structure) file.
Updated:
sometime the server.js file will be followed structured:
{
"country":"GB",
"currency":"GBP",
}
and sometimes it may have few more nested array.
{
"bank":[
{
"property":[
{
"country":"GB",
"currency":"GBP"
}
],
}
]
}
and the server.json structrue is unpredictable and we need to check only the input.json key is availble in the server.json and need to change those values irrespective of structure.
Updated - Latest:
async function getIdea(input, data)
{
var datastring = JSON.stringify(data);
Object.entries(input).forEach(([key, value]) => {
console.log(key);
console.log(value);
var re = new RegExp(`"${key}":"[^"]*"`, "g");
console.log(re);
dataString = datastring.replace(re, `"${key}":"${value}"`);
});
console.log(JSON.parse(datastring))
}
getIdea(input, data);
Input.json
{
"country":"GB",
"currency":"GBP"
}
data.json
{
"bank": [
{
"country":"US",
"currency":"USD",
}
]
}
Output Console:
country
GB
/"country":"[^"]*"/g
currency
GBP
/"currency":"[^"]*"/g
{
bank: [
{
country: 'US',
currency: 'USD',
}
]
}
There are many ways how to do this.
You can simply stringify the object you need to modify and go through the entries of input object, using regex to replace what is needed.
var updateProps = function(data, input) {
var dataString = JSON.stringify(data);
// Iterate over all entries in input object
Object.entries(input).forEach(([key, value]) => {
// matches property value string pair you are looking for
// eg.: "country": "US"
var re = new RegExp(`"${key}":"[^"]*"`, "g");
// replace what with new pair
dataString = dataString.replace(re, `"${key}":"${value}"`)
});
return JSON.parse(dataString)
}
Now you just call the function on the objects needed:
var input = {
"country": "GB",
"currency": "GBP"
}
var server1 = {
"bank": [{
"bankAccountType": "Saving",
"country": "US",
"currency": "USD",
"firstName": "TestFirstName",
"lastName": "TestLastName",
"confirmed": "true"
}]
}
var server2 = {
"bankAccountType": "Saving",
"country": "GB",
"currency": "GBP",
"firstName": "TestFirstName",
"lastName": "TestLastName",
"confirmed": "true"
}
console.log("Changed object 1: ", fn(server1, input))
console.log("Changed object 2: ", fn(server2, input))
/*
{...,"country":"US","currency":"USD",...}
chagnes to:
{...,"country":"GB","currency":"GBP",...}
*/

How do I sort a JSON by Date?

I'm trying to loop through a JSON and sort it by the date so I can see the latest date to the oldest date, and then write it to the file.
Here is my code
var reader = JSON.parse(fs.readFileSync('txt.json', 'utf8'));
function sortByDate(a, b) {
return new Date(a.lastUpdated).toJSON() - new Date(b.lastUpdated).toJSON();
}
reader.sort(sortByDate)
JSON Data Example
{
"Data": {
"Contents": [
{
"Key": [
"HelloTest"
],
"lastUpdated": [
"2019-10-25T10:30:50.558Z"
]
},
{
"Key": [
"TestHello"
],
"lastUpdated": [
"2019-03-26T10:30:50.558Z"
]
}
]
}
}
Here are a couple of errors I found in your code:
Your function name has a typo, it should be sortByDate and not sortbyDate.
You need top sort the inner json.Data.Contents array, not the outer json object.
You need to reference the first element of your lastUpdated arrays using lastUpdated[0].
Finally, you do not need to call toJSON() on the date objects in your sorting function, simply convert to date and return the difference.
Also your inner data fields are arrays, which seems strange for a Key and a lastUpdated value.
If you keep your fields as arrays, here is a working example showing how to sort the inner Data.Contents array by date:
const jsonString = `{
"Data": {
"Contents": [{
"Key": ["HelloTest"],
"lastUpdated": ["2019-10-25T10:30:50.558Z"]
}, {
"Key": ["TestHello"],
"lastUpdated": ["2019-03-26T10:30:50.558Z"]
}]
}
}`;
function sortByDate(a, b) {
return new Date(a.lastUpdated[0]) - new Date(b.lastUpdated[0]);
}
const json = JSON.parse(jsonString);
const defaultValue = { Data: { Contents: [] } };
const sortedContents = [...(json || defaultValue).Data.Contents].sort(sortByDate);
const output = { ...json, Data: { Contents: sortedContents } };
console.log(output);
If you change your fields to scalars, which I suggest, here is another example:
const jsonString = `{
"Data": {
"Contents": [{
"Key": "HelloTest",
"lastUpdated": "2019-10-25T10:30:50.558Z"
}, {
"Key": "TestHello",
"lastUpdated": "2019-03-26T10:30:50.558Z"
}]
}
}`;
function sortByDate(a, b) {
return new Date(a.lastUpdated) - new Date(b.lastUpdated);
}
const json = JSON.parse(jsonString);
const defaultValue = { Data: { Contents: [] } };
const sortedContents = [...(json || defaultValue).Data.Contents].sort(sortByDate);
const output = { ...json, Data: { Contents: sortedContents } };
console.log(output);
It looks like you're reading contents from a file, then needs to sort it by date, and then finally write it to a new file. If that is what you're going for, the following should help:
const fs = require('fs');
const path = require('path');
// JSON files can be requied in as objects without parsing
// `arrayOfStuff` will be the var name for `Contents`
const { Data: { Contents: arrayOfStuff } } = require('./data.json');
function sortByDate(el1, el2) {
// access the date from the object and turn into date object
let date1 = new Date(el1.lastUpdated[0]);
let date2 = new Date(el2.lastUpdated[0]);
// compare date objects in revers order to get newest to oldest
return (date2 - date1);
}
// sort `Contents` from the `Data` object and turn into JSON
const sortedContent = arrayOfStuff.sort(sortByDate);
const newDataObj = JSON.stringify({ Data: { Content: sortedContent }}, null, 2);
// create the fully qualified file path with `sortedByDate.json` as the file name
const filePath = path.resolve('./', 'sortedByDate.json');
// write to new file
fs.writeFile(filePath, newDataObj, (err) => {
if(err) {
console.log('Made an oopsie:', err);
}
console.log(`Success!, new JSON file located at: ${filePath}`);
}); // write to file

Array of key-value pair JSON object parsing

Hi I have have a given array of JSON object in a file:
file.json:
[
{
"id": "xccdf_saphana.content_profile_test1",
"info": {
"applicable_platforms": ["SUSE", "RHEL", "SUSE FOR SAP APP"],
"applicable_workloads": "SalesPromo",
"applicable_compliance": "CIS",
"type":"System"
}
},
{
"id": "xccdf_saphana.content_profile_test2",
"info": {
"applicable_workloads": "SalesPromo",
"applicable_compliance": "CIS",
"type":"System"
}
}
]
Below is the way I am reading it.
var obj = JSON.parse(fs.readFileSync(file.json, 'utf8')); // read the file
myID = "xccdf_saphana.content_profile_test2";
var myInfo = getInfobyID(myID);
function getInfobyID(myID) {
// Got messed up, tried changing JSON structure multiple time, so that I can easily parse it.
for(var i=0; i < obj.length; ++i) {
if(obj[i].id == myID)
return obj[i].info;
}
}
Is their any way I can optimize it, as I will be recursively searching for multiple myID later.
Turn your json into an object rather than an array. Then you can make quick lookups.
let hash = obj.reduce((agg, e) => {
agg[e.id] = e;
return agg;
}, {});
let value = hash["xccdf_saphana.content_profile_test2"].info;
The naming 'obj' is a bit confusing here since it is actually an array of objects (from the JSON file).
Try something like:
var myArrOfObj = JSON.parse(fs.readFileSync(file.json, 'utf8'));
var myID = "xccdf_saphana.content_profile_test2";
var myInfo = getInfobyID(myID);
function getInfobyID(myID){
var matchingObj = myArrOfObj.find((obj) => obj.id === myID);
// Fallback to empty string since there might be no match.
return (matchingObj) ? matchingObj.info : '';
}
You can use Array.reduce to convert your array into an object with key as id and value as info.
Now you can just return the object[id] and get the info without iterating everytime.
var json = [{
"id": "xccdf_saphana.content_profile_test1",
"info": {
"applicable_platforms": ["SUSE", "RHEL", "SUSE FOR SAP APP"],
"applicable_workloads": "SalesPromo",
"applicable_compliance": "CIS",
"type": "System"
}
},
{
"id": "xccdf_saphana.content_profile_test2",
"info": {
"applicable_workloads": "SalesPromo",
"applicable_compliance": "CIS",
"type": "System"
}
}
];
var data = json.reduce((acc, curr) => {
acc[curr.id] = curr.info;
return acc;
}, {});
function getInfobyID(data, id) {
return data[id];
}
console.log(getInfobyID(data, "xccdf_saphana.content_profile_test2"));
Based on this requirement:
Is their any way I can optimize it...
You may want to store the ID value as the key of a map, and any info related to it as the value. This way, whenever you are searching, if you already have the ID yo can access the data for that ID in constant time, or O(1), as opposed to linear time, or O(n).
This is the only way to speed up your search without more complex data structures, but it comes with one caveat which is that you no longer have a list. You will be using a map.
Change this:
[
{
"id": "xccdf_saphana.content_profile_test1",
"info": {
"applicable_platforms": ["SUSE","RHEL","SUSE FOR SAP APP"],
"applicable_workloads": "SalesPromo",
"applicable_compliance": "CIS",
"type":"System" }
},
{
"id": "xccdf_saphana.content_profile_test2",
"info": {
"applicable_workloads": "SalesPromo",
"applicable_compliance": "CIS",
"type":"System" }
}
]
To this:
{
"xccdf_saphana.content_profile_test1": {
"applicable_platforms": ["SUSE","RHEL","SUSE FOR SAP APP"],
"applicable_workloads": "SalesPromo",
"applicable_compliance": "CIS",
"type":"System"
},
"xccdf_saphana.content_profile_test2": {
"applicable_workloads": "SalesPromo",
"applicable_compliance": "CIS",
"type":"System"
}
}
Now you don't need any loops. You just have one object, with each member of the object representing a different item.
In your code, you can simply do obj[myId] and you will either get undefined if it doesn't exist, or you will get an object of the matching result.
This is the fastest a search could possibly be, but again it requires a map-like data structure and not a list.
If you absolutely must use a list, the only real optimization to be made is as follows:
Cache your list length, so you do not have to calculate it on each iteration of the loop
Your new getInfobyID could look like this:
function getInfobyID(myID){
var len = obj.length;
for (var i=0; i < len; ++i){
if( obj[i].id == myID)
return obj[i].info;
}
}

Categories