Access deeply nested object & build CSV file using Javascript - javascript

I'm fetching data using API and Im receiving an array of objects. I want to extract the Timestamp & Result to CSV file. Im unsure how could I access those objects and how to store them in CSV as Im a beginner of javascript, any advise would be very much appreciated
My code:
const url = "https://api2.branch.io/v1/query/analytics";
await fetch(url, {
method: "POST",
headers: {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36",
Accept: "application/json; charset=UTF-8"
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then((data) => {
Object.keys(data).forEach(key => {
console.log(data[key]);
});
})
.catch(error => {
console.log(error);
})
};
//callback function
callApi();
The output of the console.log(data[key]):
[
{
timestamp: '2021-05-04T00:00:00.000+08:00',
result: {
last_attributed_touch_data_tilde_campaign: 'Broad',
last_attributed_touch_data_tilde_advertising_partner_name: 'Google',
last_attributed_touch_data_tilde_campaign_id: null,
unique_count: 7483928
}
},
{
timestamp: '2021-05-04T00:00:00.000+08:00',
result: {
last_attributed_touch_data_tilde_campaign: 'Today',
last_attributed_touch_data_tilde_advertising_partner_name: 'Yahoo',
last_attributed_touch_data_tilde_campaign_id: null,
unique_count: 43535345
}
},
{
timestamp: '2021-05-04T00:00:00.000+08:00',
result: {
last_attributed_touch_data_tilde_campaign: 'IOS',
last_attributed_touch_data_tilde_advertising_partner_name: 'Facebook',
last_attributed_touch_data_tilde_campaign_id: null,
unique_count: 747473
}
}
]

You first need to convert all data into CSV format. Here's one way you can do this, added comments to help you understand what is happening:
// where the csv data will be saved to
let csv = [];
// loops through each object in the 'data' array
for (let i = 0; i < data.length; i++) {
// this builds the CSV headers as the first line of the csv data
// i === 0 makes sure to only target the first object in the 'data' array
if (i === 0) {
let title = [];
// adds 'timestamp' key to the title array
title.push('timestamp');
// loops through all the 'result' keys, adds them to the growing title array
for (let key in data[i].result) {title.push(key);}
// format then collapses the array into a string, separated by commas to the csv array
// ex: ['A', B'] turns into "A, B"
csv.push(title.map(function(item) {return '' +item + '';}).join(', '));
}
// this builds the CSV data after the first line
let row = [];
// adds the 'timestamp' value to the row array
row.push(data[i].timestamp);
// loops through all the 'result' key's data, adds them to the growing row array
for (let key in data[i].result) {row.push(data[i].result[key]);}
// formats then collapses the array into a string, separated by commas to the csv array
csv.push(row.map(function(item) {return '' +item + '';}).join(', '));
}
// collapses the csv array into a string, separated by a newline break
// ex: ['A', 'B'] turns into "A\nB"
csv = csv.join('\n');
Then you need to download the data in a CSV file format.
function downloadAsCsv(csv, file_name) {
var blob = new Blob([csv], {'type':'text/csv;charset=utf-8;'});
// Internet Explorer 10+
if (navigator.msSaveBlob) {window.navigator.msSaveBlob(blob, file_name);}
else {
var link = document.createElement('a');
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', file_name);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
Here's a full working example: https://jsfiddle.net/th5vejLc/

Related

image grabber empty url

urls returns an empty array []
I don't quite understand this part of the code myself as its borrowed,
I either need help understanding the urls part to recode it properly,
or have someone recode it for me which I will try my best to understand.
the urls part was made for google images but Im using another site.
im grabbing images of this site: https://www.desktopnexus.com/search/kitsune+girl/1/
function kitsuneimage(message) {
var options = {
url: "https://www.desktopnexus.com/search/" + "kitsune+girl" + "/" + Math.ceil(Math.random() * (60 + 2)) +"/",
method: "GET",
headers: {
"Accept": "text/html",
"User-Agent": "Chrome"
}
}
console.log(options.url);
request(options, function(error, response, responseBody) {
if (error) {
return;
}
$ = cheerio.load(responseBody);
var links = $(".image a.link");
var urls = new Array(links.length).fill(0).map((v, i) => links.eq(i).attr("href"));
console.log(urls);
if (!urls.length) {
return;
};
message.channel.send(urls[0]);
});
}
instead of
var links = $(".image a.link")
maybe this should work:
var thumbnails = $("#middlecolumn .thumbnail")
// this is a jquery object, so we need to call get() to turn it into a plain array
var links = thumbnails.map(thumbnail => thumbnail.parent()).get()
var urls = links.map(link => link.getAttribute('href'))
well the thumbnails part does grab the image and it looks like this in the console.log(thumbnails);
'2': {
type: 'tag',
name: 'img',
namespace: 'http://www.w3.org/1999/xhtml',
attribs: [Object: null prototype] {
src: '//cache.desktopnexus.com/thumbseg/1853/1853748-200.jpg',
border: '1',
alt: 'girl',
class: 'thumbnail'
},
but it says in the .parent is undefined
I was thinking maybe replace thumbnail with tag since thats the type it is, would that work?
----EDIT----
well thats wrong because thumbnail is the class of the image in this.
so why is .parent undefined?
This question is closed since I moved on to making a new code with "got" module

Javascript fetch api with unlimited timeout

I have a web worker with a fetch request that returns an error after some time.
I am not sure if it is because of timeout, but i want it to have un unlimited timeout.
This is my code inside webWorker:
fetch(data.defaults + 'returnSqlRes.php',
{
headers: {'Accept': 'application/json', 'Content-Type': 'application/json'},
method: "post",
body: JSON.stringify(data.sql)
})
.then(status)
.then(json)
.then(function (sData) {
var dt={};
dt['o']=data.tableId;
dt['data']=sData;
_.forEach(dt.data[0],function (row) {
row.DT_RowId = composeId(data.pk, row);
_.forEach( data.tableCols,function (o, index) {
if (_.has(o, 'complexList')) {
var fieldName = o.attr.desigColumn ? o.attr.desigColumn : o.attr.name;
var field = o.name;
var keys = returnListKeys(o);
var search = '';
_.forEach( keys, function (name, i) {
if (i < keys.length - 1) {
search += row[name] + '#';
} else {
search += row[name];
}
});
var result = _.find(data.loadedData[getComplexListIndex(o)], {VAL: search});
if (result == undefined) {
row[field] = "";
} else {
row[field] = result[fieldName];
}
}
});
});
self.postMessage(downloadCSV(dt));
The final purpose of code is to download a csv file. The problem is sometimes i have 150k or 200k records and it takes time to parse and a network error is downloaded instead of the file. In tables with less than 100k records everything is ok, file is downloaded.
Came Across this might help https://github.com/github/fetch/issues/175 good luck!

converting js object to csv doesnt work and no error is shown

I am trying to convert js object to csv, using jquery foreach, Here is what the object looks like
In object 0 it has email : "farhana#farhana.com" and fullname : "farhana"
I followed a example from stackover flow and I thought it works, but the CSV file doesn't get downloaded, or show me any message.
Here is the code
self.downloadCSV = function(){
$.ajax({
type: 'GET',
url: BASEURL + 'index.php/admin/getcsv/' + auth ,
contentType: 'application/json; charset=utf-8',
})
.done(function(docs) {
if(docs == null){
alert('file not found for csv');
}else{
// Here is where the foreach and storing to csv starts.
console.log(docs);
var csvContent = "data:text/csv;charset=utf-8,";
$.each(docs, function (index, doc) {
var dataString = doc.join(",");
csvContent += index < doc.length ? dataString+ "\n" : dataString;
});
var encodedUri = encodeURI(csvContent);
window.open(csvContent)
}
})
.fail(function(xhr, status, error) {
alert(error);
})
.always(function(data){
});
}
No error so not sure what to debug :( Need help.
window.open(csvContent) doesn't do anything since its not a URL.
you need to create a Blob to download content.
also your conversion from json to csv is wrong. doc.join(",") only works when doc is an Array but your picture says its an Object so you need to do it differently
var docs = [{ name: 'test', id: 22, emal: 'test#test.com' }, { name: 'test2, sample', id: 2122, emal: 'test2#test.com' }, { name: 'test3', id: 2223.23, emal: 'test3#test.com' }];
// convert js object array to csv string
// if your "doc" is an Object
var csv = docs.reduce((str, doc) => str += '"' + Object.values(doc).join('","') + '"\r\n', '"' + Object.keys(docs[0]).join('","') + '"\r\n');
// if your "doc" is an Array
// var csv = docs.reduce((str, doc) => str += '"' + doc.join('","') + '"\r\n', '');
// download csv string as blob
var blob = new Blob([csv], { 'type': 'application\/octet-stream' });
var a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = 'docs.csv';
a.click();
a.remove();

PHP strips out JSON node (array)?

I'm trying to log some stuff in a JSON file.
An entry looks like this:
{
"bookindId":"30779265",
"timestamp":"1428447744",
"plate":"D-GO9872",
"cityId":"RLD",
"zoneId":"759",
"highDemandZones":[
"402",
"429",
"714",
"715",
"721",
"728",
"732",
"734",
"742",
"756",
"758",
"763"
],
"accountId":"151426",
"date":"20150408",
"formattedDate":"08.04.2015, 01:02 Uhr"
},
But sometimes, highDemandZones is just missing:
{
"bookindId":"30779279",
"timestamp":"1428447762",
"plate":"D-GO120",
"cityId":"RLD",
"zoneId":"759",
"accountId":"151426",
"date":"20150408",
"formattedDate":"08.04.2015, 01:02 Uhr"
},
My problem is that even if there aren't any highDemandZones, it should at least be in there as an empty array. Also I can defenitely say that it shouldn't be empty either. Which leads me to the conclusion that my php code is flawed.
This is the javascript function
App.prototype.trackBooking = function() {
var self = this;
// [... stripped out other code for clarity]
// get high demand zones
var highDemandZones = [];
$.each(this.model.zoneDemands, function(id, details) {
if(details.demand == 'HIGH') {
highDemandZones.push(id);
}
});
// [... stripped out other code for clarity]
var obj = {
bookindId: this.model.user.booking.bookingId,
timestamp: Math.round(Date.now() / 1000),
plate: this.model.user.booking.vehicle.numberPlate,
cityId: this.model.city.id,
zoneId: car.zoneId,
highDemandZones: highDemandZones,
accountId: this.model.user.accountId,
date: todayFormatted,
formattedDate: day + '.' + month + '.' + year + ', ' + hours + ':' + minutes + ' Uhr'
};
return $.ajax({
type: "POST",
dataType: 'json',
url: 'php/ajax.php',
data: {
booking: obj,
action: 'trackBooking'
}
}).success(function(data) {
console.log('TRACKED');
console.log(data);
}).fail(function(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
});
};
This is php function that'll save this obj to a JSON file
function saveBooking($booking) {
// get current bookings
$json = file_get_contents("../reporting/bookings.json");
$bookingsArr = json_decode($json, true);
if(!isset($bookingsArr[$booking['date']])) {
$bookingsArr[$booking['date']] = array();
}
// push new booking into current bookings array
array_push($bookingsArr[$booking['date']], $booking);
// convert to JSON
$jsonString = json_encode($bookingsArr);
// save into JSON file
file_put_contents('../reporting/bookings.json', $jsonString);
// return JSON
echo $jsonString;
}
Do you have any ideas when this could occur? The IDs (the strings inside highDemandZones) never have extended characters like é.
There are defenitely nodes being stripped out even though the array is not empty. The JSON is valid.

Javascript - json data not being transferred into memory properly

I have a json file that contains 16,490 lines of data. Here's a snippet:
[
...
["alrightty",2 ],
["alrighttyy",1 ],
["alrighty",100 ],
["alrightyy",1 ],
["alrigt",1 ],
...
]
This data will be used for my sentiment analysis thesis project. I used the following code to extract the data from the json file:
var positive_words_list = {}
function readJSONFile(filename,type) {
$.ajax({
type: 'GET',
url: filename,
dataType: 'json',
success: function(data) {
switch (type) {
case "pos" : positive_words = data; break;
case "neg" : negative_words = data; break;
case "afinn" : afinn_words = data; break;
}
},
async: false
});
}
readJSONFile('js/json/positivekeywords.json','pos');
for (var i = 0; i < positive_words.length; i++) {
row = positive_words[i];
positive_words_list[row[0]] = row[1];
};
What this code does is extract the data from the json file and then put it in a 1-dimensional array with each word as an array index and the number as the value.
Now I have this code run when the site loads inside $(function() { ... }); so positive_words_list should contain the data on load time. The thing is after the site loads and I do positive_words_list.length in the console, it outputs 63. As I said, there should be 16,490 entries.
Did I miss something? What am I doing wrong?
Thanks!
John
EDIT: I should add that when I do a positive_words.length in the console, I get the correct number of elements, 164,950
As far as I can see positive_words_list is a JavaScript object that does not have length property out of the box. So the only reason why you get the magic number 63 is because your array of arrays contain entity with word length as a first item; something like:
[
...
['length', 63],
...
]
In order to get number of keys in JavaScript Object you can either do Object.keys(positive_words_list).length or iterate over all properties and increment the counter:
function size(obj) {
var key,
counter = 0;
for(key in obj) {
if(obj.hasOwnProperty(key)) {
counter++;
}
}
return counter;
}
size(positive_words_list); // <- will return number of properties in object
Your snippet may be modified in the following manner:
HTML
<h1 id="data">Number of positive words is ...</h1>
JavaScript
$(function(){
var positive_words,
positive_words_list = {};
function readJSONFile(filename,type) {
$.ajax({
type: 'GET',
url: filename,
dataType: 'json',
success: function(data) {
switch (type) {
case "pos" : positive_words = data; break;
case "neg" : negative_words = data; break;
case "afinn" : afinn_words = data; break;
}
},
async: false
});
}
readJSONFile('data.json','pos');
for (var i = 0; i < positive_words.length; i++) {
row = positive_words[i];
positive_words_list[row[0]] = row[1];
};
$('#data').html('Number of positive words is ' + Object.keys(positive_words_list).length);
});
Plunker: http://plnkr.co/edit/uhHZ1zEuUHXHIQrd1BVa?p=preview
positive_words_list is an object, not an array, so you should result in:
positive_words_list["alrightty"] === 2
positive_words_list["alrighttyy"] === 1
and so forth. You can get an array of the keys of the object using:
Object.keys(positive_words_list)
Object.keys(positive_words_list).length
Which will return an array of the keys of your object. Note that Object.keys is an ES5 feature available in most current browsers.

Categories

Resources