How to convert a JSON into a Hashmap in NodeJS - node.js

I am attempting to convert a HTTP request body in JSON format into a hashmap. Below is how my request looks:
{
"car": [{
"ford": "focus",
"audi": "a6"
}],
"food": [{
"soup": "leek"
}]
}
And below is the code I have tried so far:
const express = require('express');
const router = express.Router();
router.post('/items', async (req, res) => {
res.setHeader('Content-Type', 'application/json');
let jsonString = JSON.stringify(req.body);
let jsonObject = JSON.parse(jsonString);
let jsonMap = new Map(Object.entries(jsonObject));
var mainArray = {};
var carKey = 'car';
mainArray[carKey] = [];
for (var entry of jsonMap.entries()) {
let key = entry[0], value = entry[1];
let innerJson = JSON.stringify(value);
let innerJsonObj = JSON.parse(innerJson);
for(var innerKey in innerJsonObj) {
let tempStr = JSON.stringify(innerJsonObj[innerKey]);
let tempVal = JSON.parse(tempStr);
let attr = '';
let param = '';
for(var k in tempVal) {
attr = k;
param = tempVal[k];
logger.info(k + "=" + tempVal[k]);
}
let result = someMethod(param);
var carData = {
attr : JSON.stringify(result);
}
mainArray[carKey].push(carData);
}
}
});
I want to display the results in the same way as received in the request, but with the use of the binary result of someMethod(). Below is what im trying to create as a response.
{
"car": [
{
"ford": "binarydata",
"audi": "binarydata"
}
],
"food": [
{
"soup": "binarydata"
}
]
}

I have managed to achieve this using the code below. This allows me to specify the key and value in the JSON I add to the array via the push() command. Thank you for the guidance.
var carData = {};
carData[attr] = JSON.parse(JSON.stringify(`${result}`));
mainArray[carKey].push(carData);

Related

Creating HMAC BodyHash Sha256 nodejs

I am trying to integrate with a service (paysera https://developers.paysera.com/) that uses HMAC Authentication. I've manage to integrate every GET endpoint. Nevertheless, when it comes to the POST request it seems the code is not working.
createHMACAuth(data) {
let bodyHash = crypto.createHash('sha256').update(JSON.stringify(data)).digest('base64');
let method = 'POST';
let path = `/rest/v1/transfers`;
let ts = moment().unix();
let nonce = GUID(32);
let port = 443;
let macString = `${ts}\n${nonce}\n${method}\n${path}\n${host}\n${port}\n${bodyHash || ''}\n`;
let my_mac_key = 'my_mac_key';
let my_mac_id = 'my_mac_id';
let mac = crypto.createHmac('sha256', my_mac_key).update(macString).digest('base64');
let headerString = `MAC id="${my_mac_id}", ts="${ts}", nonce="${nonce}", mac="${mac}", ext="body_hash=${bodyHash}"`;
return headerString;
}
let data = {
key: 'value',
otherkey: 'othervalue'
};
let headers = {
Host: 'wallet.paysera.com',
'User-Agent': `Paysera node.js library`,
mac_id: 'my_mac_id',
Authorization: createHMACAuth(data);
};
POST_REQUEST(`${headers.host}/rest/v1/transfers`, data, headers, (err, res) => console.log(res))
The response I get is:
{
error: 'unauthorized',
error_description: 'Given MAC content body hash does not match actual hash of content'
}
Any help will be much appreciated!
I had an error when generating the body_hash
Fix
createHMACAuth(method, path, data) {
let bodyHash, ext;
if (method === 'POST') {
ext = `body_hash=${encodeURIComponent(this.createHash(JSON.stringify(data)))}`;
}
this.method = method;
this.path = `/${path}`;
let nonce = `${U.GUID(32)}`;
let port = 443;
let macString = `${this.ts}\n${nonce}\n${this.method}\n${this.path}\n${this.host}\n${port}\n${ext || ''}\n`;
let mac = this.createHMACHash(macString);
let headerString = `MAC id="${this.mac_id}", ts="${this.ts}", nonce="${nonce}", mac="${mac}"`;
if (method === 'POST') headerString += `, ext="${ext}"`
return headerString;
}
Your answer helped me make it work. Full code for other people that might need this.
import crypto from 'crypto'
import fetch from 'node-fetch'
function createHash(data) {
return crypto.createHash('sha256').update(data).digest('base64');
}
function createHMACHash (macKey, macString) {
return crypto.createHmac('sha256', macKey).update(macString).digest('base64');
}
async function createHMACAuth() {
const macId = 'your-mac-id';
const macKey = 'your-mac-key';
const ts = new Date().getTime();
const nonce = 'nQnNaSNyubfPErjRO55yaaEYo9YZfKYU';
const method = 'POST';
const uri = '/rest/v1/transaction'
const host = 'wallet.paysera.com'
const port = 443;
const data = {
"payments": [
{
"description": "Payment for order No. 1234",
"price": 1299,
"currency": "EUR",
"parameters": {
"orderid": 1234
}
}
],
"redirect_uri": "http://www.example.com/somePage"
}
let ext;
if (method === 'POST') {
ext = `body_hash=${encodeURIComponent(createHash(JSON.stringify(data)))}`;
}
let macString = `${ts}\n${nonce}\n${method}\n${uri}\n${host}\n${port}\n${ext || ''}\n`;
let mac = createHMACHash(macKey, macString);
let headerString = `MAC id="${macId}", ts="${ts}", nonce="${nonce}", mac="${mac}"`;
if (method === 'POST') headerString += `, ext="${ext}"`
const response = await fetch(`https://${host}${uri}`,{
method:method,
headers:{
Authorization: headerString,
'Content-Type':'application/json'
},
body: JSON.stringify(data)
})
return headerString;
}
await createHMACAuth()

.push is not a function in web crawler

I am writing a node JS web crawler class, and I have encountered the following error, this.textInvertedIndex[word].push is not a function. Upon further inspection I realised that for some reason this.textInvertedIndex[word] was written as a native object, function Object({ [native code] }). For the first few iterations, by console logging this.textInvertedIndex everything seemed fine as it was an object of arrays. But then suddenly this error occurred. Is there any part of the code where I am implicitly rewriting textInvertedIndex?
Here is the relevant class:
function Crawler(queue, maxIndexSize) {
this.queue = queue;
this.maxIndexSize = maxIndexSize;
this.findChunks = () => {
let currentChunk;
let minimumDistance = Infinity;
for (i = 1; i <= this.maxIndexSize; i++) {
if (this.maxIndexSize % i === 0) {
const newDistance = Math.abs(i - 30);
if (newDistance < minimumDistance) {
minimumDistance = newDistance;
currentChunk = i;
} else {
return currentChunk
};
};
};
};
this.chunks = this.findChunks();
this.chunkSize = this.maxIndexSize / this.chunks;
this.totalWordOccurances = {};
this.imageInvertedIndex = {};
this.textInvertedIndex = {};
this.images = [];
this.sites = [];
this.seen = {};
this.write = (url, html) => {
const documentId = this.sites.length;
const website = new Website(url, html);
const title = website.title();
const content = website.content(title);
const words = content.filter(item => typeof item !== "object");
const wordsLength = words.length;
const query = new Query(words);
const individualWords = query.individualize(words);
this.seen[url] = true;
this.sites.push({
url,
title,
description: website.description()
});
for (word of individualWords) {
const normalizedTf = query.count(word) / wordsLength;
const textInvertedIndexEntry = {
documentId,
normalizedTf
};
if (this.textInvertedIndex[word]) {
this.textInvertedIndex[word].push(textInvertedIndexEntry);
} else {
this.textInvertedIndex[word] = [textInvertedIndexEntry];
};
if (this.totalWordOccurances[word]) {
this.totalWordOccurances[word] += 1;
} else {
this.totalWordOccurances[word] = 1;
};
};
for (i = 0; i < content.length; i++) {
const item = content[i];
if (typeof item === "object") {
const imageId = this.images.length;
this.images.push(item);
for (word of individualWords) {
const imageScore = getImageScore(i, word, content);
const imageInvertedIndexEntry = {
imageId,
imageScore
};
if (this.imageInvertedIndex[word]) {
this.imageInvertedIndex[word].push(imageInvertedIndexEntry);
} else {
this.imageInvertedIndex[word] = [imageInvertedIndexEntry];
};
};
};
};
};
this.crawl = async () => {
while (this.sites.length !== this.maxIndexSize) {
let nextQueue = [];
const websitesUnfiltered = await Promise.all(this.queue.map((url) => {
const website = new Website(url);
return website.request();
}));
const websitesToAdd = this.maxIndexSize - this.sites.length;
let websites = websitesUnfiltered.filter(message => message !== "Failure")
.slice(0, websitesToAdd);
for (site of websites) {
const url = site.url;
const htmlCode = site.htmlCode;
const website = new Website(url, htmlCode);
this.write(url, htmlCode);
nextQueue = nextQueue.concat(website.urls());
};
nextQueue = new Query(nextQueue.filter(url => !this.seen[url]))
.individualize();
this.queue = nextQueue;
};
};
};
Called like this
const crawler = new Crawler(["https://stanford.edu/"], 25000000);
crawler.crawl();
this.textInvertedIndex = {}; is defining an Object of which push is not a valid function. you can change it to an array by defining it as this.textInvertedIndex = []; otherwise you can add key/value entries to the object as it is defined like this: this.textInvertedIndex[key] = value;
Turns out, my key was accessing this.textInvertedIndex[word]. And word was constructor. constructor is already a built in object property so it can never be rewritten as an array with .push defined. To solve this problem, make all object keys capital, so constructor will become CONSTRUCTOR, thus making sure that already existing object properties are never called.

How to return key value pair array in res.json() in node.js?

I am generating a key-value pair array in my code, but when I pass the array in res.json() I am receiving null on front-end.
This is the key-value array that I want to pass. Any Idea what I am not doing right?
router.post('/xlsData', session, async (req, res)=>{
const reqStatus = req.body.searchType;
const reportDate = req.body.reportDate;
const userBebitReq = await debitReq.find({ reqStatus : reqStatus, reqType: "Debit", reqDate : reportDate},{_id : 1, userId: 1,reqAmount : 1, withdrawalMode: 1, reqDate: 1, });
let userIdArray = [];
let debitArray = [];
for(index in userBebitReq)
{
let reqAmount= userBebitReq[index].reqAmount;
let withdrawalMode= userBebitReq[index].withdrawalMode;
let reqDate= userBebitReq[index].reqDate;
let user = userBebitReq[index].userId;
let rowId = userBebitReq[index]._id;
let userKi = mongoose.mongo.ObjectId(user);
userIdArray.push(userKi);
debitArray[userKi] = {
rowId : rowId,
userId : userKi,
reqAmount: reqAmount,
withdrawalMode: withdrawalMode,
reqDate: reqDate
}
}
let user_Profile = await userProfile.find({ userId: { $in: userIdArray } });
for(index in user_Profile)
{
let id = user_Profile[index].userId;
if(debitArray[id]){
debitArray[id].address = user_Profile[index].address;
debitArray[id].city = user_Profile[index].city;
debitArray[id].pincode = user_Profile[index].pincode;
debitArray[id].name = user_Profile[index].account_holder_name;
debitArray[id].account_no = user_Profile[index].account_no;
debitArray[id].bank_name = user_Profile[index].bank_name;
debitArray[id].ifsc = user_Profile[index].ifsc_code;
debitArray[id].paytm_number = user_Profile[index].paytm_number;
}
}
res.json({
status : 1,
data : debitArray
})
})
Receiving this on front-end :
data: Array(0)
Do it like this:
let debitArray = {};
instead of this.
let debitArray = [];
You are basically using object not array.

Node.js - How to get data from json file and use that data to set custom attributes in xml

Well I want to read json file in my node.js code to update the XML tags in the given XML, suppose I have a file named as object.json, now I want to Get its data, data in object.json is
{
"input": {
"customClass": "input",
"customModule": "abcInput",
"customModuleProvider": "Whatever"
},
"button": {
"customClass": "ViewController",
"customModule": "Testing",
"customModuleProvider": "target"
}
}
I have tried to print data but I was not able to use that data to set attributes, I tried to set attributes for hard coded tags, code for that is
var DOMParser = new (require('xmldom')).DOMParser({ normalizeTags: { default: false } });
var express = require("express"),
bodyParser = require('body-parser');
require("body-parser-xml")(bodyParser);
var xml2js = require('xml2js');
var builder = new xml2js.Builder({ standalone: { default: false } });
var app = express();
//Options of body-parser-xml module
app.use(bodyParser.xml({
xmlParseOptions: {
normalize: false, // Trim whitespace inside text nodes
normalizeTags: false, // Transform tags to lowercase
explicitArray: false // Only put nodes in array if >1
}
}));
//Post Method
app.post('/users', function (req, res, body) {
//Parsing Request.Body
var document = DOMParser.parseFromString(
builder.buildObject(req.body).toString()
);
//Getting a list of elements whose name is being given
var node = document.getElementsByTagName("TextView");
//Changing Tag Name of Specific Elements
for (var i = 0; i < node.length; i++) {
node[i].tagName = "com.mycompany.projectname.TextView";
}
//Getting a list of elements whose name is being given
var node = document.getElementsByTagName("com.example.usmanchattha.custom.TextView");
//Setting attributes
for (var i = 0; i < node.length; i++) {
node[i].setAttribute("android:id", "#+id / text2");
node[i].setAttribute("android:text", "Custom Android Font");
node[i].setAttribute("customfontdemo:chattha", "faizan");
node[i].setAttribute("android:padding", "12dp");
node[i].setAttribute("customfontdemo:fontName", "pipe_dream.ttf");
node[i].setAttribute("android:textSize", "32sp");
}
//Responsing Updated Data
res.send(document.toString());
});
app.listen(1000);
Well I ran into same problem, and then after a hard work I made a solution for this problem, here is the code that I created, it works perfectly fine, if you have any query, please make sure to ask.
var express = require("express"),
bodyParser = require('body-parser');
var DOMParser = new (require('xmldom')).DOMParser({ normalizeTags: { default: false } });
var arrayOfControls = require('./object.json'); //to read object.json file
var app = express();
app.use(bodyParser.text({ type: '*/*' }));
app.post('/users', function (req, res, body) {
var document = DOMParser.parseFromString(
req.body
);
var ControlNames = Object.keys(arrayOfControls); //Returns Control Names
for (var singleControl = 0; singleControl < ControlNames.length; singleControl++) {
var wholeObject = arrayOfControls[ControlNames[singleControl]]; //Returns Property names of index[i] control as an object
var PropertyNames = Object.keys(wholeObject); //returns properties of first control
var listOfElements = document.getElementsByTagName(ControlNames[singleControl]);
if (listOfElements.length < 0) {
continue;
} else {
for (var singleElement = 0; singleElement < listOfElements.length; singleElement++) {
for (var singleProperty = 0; singleProperty < PropertyNames.length; singleProperty++) {
listOfElements[singleElement].setAttribute(PropertyNames[singleProperty], wholeObject[PropertyNames[singleProperty]].toString());
}
}
}
}
req.body = document.toString();
res.send(document.toString());
});
app.listen(1000);

How to use fs.watchFile to reload Json File

I have couple functions that re-structure the JSON file. They write and manipulate one another. They are in the same js file. Every function depends on the function before to run properly. But since every one of them manipulates the file synchronously after reading it, I have encountered a problem which is hard to explain for me because I am not sure if I understand it well. When the first function finishes the task second function can't read it(It reads but can't see the updated object and its property). If I run all the functions one by one and restart the program afterward, it reads very well. Here is what I have tried until now;
I tried to make my functions asynchronous
I tried to use setTimeout function and give it up until 10 seconds
Both did not work for me. I read in StackOverflow that it fs.watch could help me but couldn't find a proper explanation of how to implement that. Any help regarding this issue I am having would be much appreciated.
-I know I can use another database but I just want to know this one because I am regularly using this. Please don't be rude if I am stupid :P
const fs = require('fs');
const ReadRawData= fs.readFileSync('Data.json');
const ReadParsed = JSON.parse(ReadRawData);
fs.watchFile('Data.json', (curr, prev) => {
console.log(`the current mtime is: ${curr.mtime}`);
console.log(`the previous mtime was: ${prev.mtime}`);
});
I just want to know how can I reload this ReadParsed everytime a file changed and can reach the reloaded version from functions.
Here is my full code; This is testing2.js
const request = require('request');
const cherio= require('cheerio');
const fs = require('fs');
const cheerioTableparser = require('cheerio-tableparser');
async function htmlCollector () {
const ReadTransactionBase = await fs.readFileSync('transactionDatabase.json');
const ReadTransaction = JSON.parse(ReadTransactionBase);
ReadTransaction.pageInformation = "";
let editedDataBase = JSON.stringify(ReadTransaction, null, 2);
fs.writeFileSync('transactionDatabase.json', editedDataBase);
for (let counter = 1; counter <= ReadTransaction.maxPage; counter++) {
request(ReadTransaction.link + counter,
(error, response, html) => {
if (!error && response.statusCode === 200) {
const $ = cherio.load(html);
const items = [];
$('#maindiv').each(function (i, elem) {
items[i] = $(this).html();
});
let newPage = {['PageNumber'+counter] : items};
ReadTransaction.pageInformation = Object.assign(newPage,ReadTransaction.pageInformation);
let editedDataBase = JSON.stringify(ReadTransaction, null, 2);
fs.writeFileSync('transactionDatabase.json', editedDataBase);
}
})
}
}
async function databaseModifier () {
const ReadTransactionBase = await fs.readFileSync('transactionDatabase.json');
const ReadTransaction = JSON.parse(ReadTransactionBase);
delete ReadTransaction.from;
delete ReadTransaction.quantities;
delete ReadTransaction.orangeBox;
let editedDataBase = JSON.stringify(ReadTransaction, null, 2);
console.log('test');
fs.writeFileSync('transactionDatabase.json', editedDataBase);
for (let i=1; i<=Object.keys(ReadTransaction.pageInformation).length;i++) {
let nums = 'PageNumber' + i;
let newObject = {[nums]: {}};
ReadTransaction.from = Object.assign(newObject,ReadTransaction.from);
ReadTransaction.orangeBox = Object.assign(newObject,ReadTransaction.orangeBox);
ReadTransaction.quantities = Object.assign(newObject,ReadTransaction.quantities);
let editedDataBase = JSON.stringify(ReadTransaction, null, 2);
fs.writeFileSync('transactionDatabase.json', editedDataBase);
}
}
async function fromOrangeBoxQuantities () {
const ReadTransactionBase = await fs.readFileSync('transactionDatabase.json');
const ReadTransaction = JSON.parse(ReadTransactionBase);
for (let counter = 1; counter <= ReadTransaction.maxPage ; counter++) {
let HTMLPageNumber = 'PageNumber' + counter;
let $ = cherio.load(ReadTransaction.pageInformation[HTMLPageNumber][0]);
cheerioTableparser($);
let data = $('.table').parsetable(true,true,true);
for (let sCounter = 1; sCounter <= data[2].length; sCounter++) {
let fromTable = {[sCounter] : [data[2][sCounter-1]]};
let orangeBoxTable = {[sCounter] : [data[3][sCounter-1]]};
let quantityTable = {[sCounter] : [data[5][sCounter-1]]};
ReadTransaction.from[HTMLPageNumber] = Object.assign(fromTable,ReadTransaction.from[HTMLPageNumber]);
ReadTransaction.orangeBox[HTMLPageNumber] = Object.assign(orangeBoxTable,ReadTransaction.orangeBox[HTMLPageNumber]);
ReadTransaction.quantities[HTMLPageNumber] = Object.assign(quantityTable,ReadTransaction.quantities[HTMLPageNumber]);
let editedDataBase = JSON.stringify(ReadTransaction, null, 2);
fs.writeFileSync('transactionDatabase.json', editedDataBase);
}
}
}
async function validatorOfTransactions (){
const ReadTransactionBase = await fs.readFileSync('transactionDatabase.json');
const ReadTransaction = JSON.parse(ReadTransactionBase);
ReadTransaction.validQuantities = [];
let editedDataBase = JSON.stringify(ReadTransaction, null, 2);
fs.writeFileSync('transactionDatabase.json', editedDataBase);
for (let counter = 1; counter <= ReadTransaction.maxPage ; counter++) {
let HTMLPageNumber = 'PageNumber' + counter;
let length = Object.keys(ReadTransaction.from[HTMLPageNumber]).length;
for (let sCounter = 1; sCounter <= length; sCounter++) {
let a = ReadTransaction.from[HTMLPageNumber][sCounter].toString();
let b = ReadTransaction.fromAddress;
let c = ReadTransaction.orangeBox[HTMLPageNumber][sCounter].toString();
let d = ReadTransaction.OrangeBox;
if (a === b && c === d) {
console.log('yay');
ReadTransaction.validQuantities.push(parseFloat(ReadTransaction.quantities[HTMLPageNumber][sCounter].toString().replace(/,/g,'')));
let editedDataBase = JSON.stringify(ReadTransaction, null, 2);
fs.writeFileSync('transactionDatabase.json', editedDataBase);
}
}
}
}
async function finalizeCalculation () {
const ReadTransactionBase = await fs.readFileSync('transactionDatabase.json');
const ReadTransaction = JSON.parse(ReadTransactionBase);
let NewArray = ReadTransaction.validQuantities;
return NewArray.reduce((a,b) => a +b, 0);
}
module.exports = {
htmlCollector : htmlCollector,
databaseModifier : databaseModifier,
fromOrangeBoxQuantities : fromOrangeBoxQuantities,
validatorOfTransactions : validatorOfTransactions,
finalizeCalculation : finalizeCalculation
};
This is transactionDatabase.json;
{
"link": "https://etherscan.io/token/generic-tokentxns2?contractAddress=0xaf2de5cb07d8f5de2369ff104150fef9dc0e604b&mode=&a=0x11209cbc2ea8cf829aa5aa1cdc5a4e5962e70655&p=",
"maxPage": 12,
"fromAddress": "0x11209cbc2ea8cf829aa5aa1cdc5a4e5962e70655",
"OrangeBox": "OUT",
"validQuantities": [],
"pageInformation": {}
}
this is newtest.js;
let testing2 = require('./testing2');
testing2.htmlCollector().then(() => testing2.databaseModifier().then(()=> testing2.fromOrangeBoxQuantities().then(()=> testing2.validatorOfTransactions().then())));
Here is the error I am getting;
(node:21760) UnhandledPromiseRejectionWarning: TypeError: Cannot read property '0' of undefined

Resources