mapping JSON to an Object - javascript

I have a JSON file that was converted from a csv and is too big to hand edit. Its' syntax is one large array I think. The data is from a group of routers and I aim to build router objects. The way the current CSV to JSON file is organized by each row and I want to pick out each router and have an object with router name, the all bandwidth measurements associated with that router.
How would you approach this? I'm attempting to take care of all of this when I iterate through the JSON file and when the router changes, I start a new instance of the router object. I'm a no longer a newb, just a slow learner. So would the next step be to create a router class with js and populate the class with what I pull out of my giant JSON array, or could/should I do with out the handwritten class and create all the objects on the fly? (can I create objects on the fly.
Current JSON (it goes on for pages, each router having a few hundred entries in the csv:
[
{
"Router": "RouterID1",
"TimeStamp": "2012/01/01 06:00:00",
"transferBytes": "23235",
"ReceivedBytes": "29903"
},
{
"Router": "RouterID1",
"TimeStamp": "2012/01/01 06:05:00",
"transferBytes": "21235",
"ReceivedBytes": "22103"
}
{
"Router": "RouterID2",
"TimeStamp": "2012/01/01 06:00:00",
"transferBytes": "23235",
"ReceivedBytes": "29903"
},
{
"Router": "RouterID2",
"TimeStamp": "2012/01/01 06:05:00",
"transferBytes": "21235",
"ReceivedBytes": "22103"
}
]
#amnotiam: the router types are gauranteed to be adjecent to each other
This might not be valid but here is the structure I think I'm going for:
[
{
"Router": "RouterID1"
"TimeStamp": array of timestamps
"transferBytes": array of bytes transferred for each timestamp
"ReceivedBytes": array of bytes received for each timestamp
},
{
"Router": "RouterID2",
"TimeStamp": array of timestamps
"transferBytes": array of bytes transferred for each timestamp
"ReceivedBytes": array of bytes received for each timestamp
}
]
#Bergi I want to make an object for each router with there historical data contained with in the object. Right know I have an object for every time entry. (I think)
#Rick Good call, I will be and will probably ask that question later:)

You can really just create the objects on the fly. It's not going to be any faster to hardcode a set of router objects, and it's likely you'll make mistakes by handwriting.
Take a look at this : http://jsfiddle.net/aSbm6/

I would start with turning the json into a php variable, so that you can operate on it more easily. It looks like your Json is one big array of objects, so it would look like this:
$routerArray = json_decode($yourJsonString);
Then you can iterate and get your data:
$newRouterObjectsArray = array();
foreach($routerArray as $routerObject) {
if (empty($newRouterObjectsArray[$Router])) {
// instantiate new router here:
$newRouterObjectsArray[$Router] = new Router([params]);
}
// any other logic, assuming that the router does exist
}
If you're doing this directly in javascript, it would look like:
var routerArray = JSON.parse([yourJsonString]);
var newRouterObjects = {};
for (routerEntry in routerArray) {
if ('undefined' == typeof newRouterObjects[routerEntry->Router]) {
//if this router doesn't exist yet, create it
newRouterObjects[routerEntry->Router] = new Router([params]);
}
// update totals, etc.
}

JSON.parse--or your library's equivalent--if given your JSON file, will return an array of objects, so you don't need to create objects.
If we call data the JSON string in your example then:
var routers = JSON.parse(data);
routers[0].Router === "DWG-350"; // true
routers[1].TimeStamp === "2012/01/01 06:05:00"; // true
routers[0].Router === routers[1].Router; // true
routers[0].TimeStamp === routers[1].TimeStamp; // false
If you need to do logic or filtering then you can use all the objects in routers as Javascript objects, because they are.
It's unclear exactly what you're trying to do, though.
I think this is the logic that you want:
var routers = JSON.parse(data), // or jQuery.parseJSON()
aggregate = {};
for (var i = 0, max = routers.length;
i < max;
i++) {
var router = routers[i];
if (typeof aggregate[routers[i].Router] === 'undefined') {
aggregate[router['Router']] = {"TimeStamp": [],
"ReceivedBytes": []}
"TransferredBytes": []};
}
aggregate[router['Router']]["TimeStamp"]
.push(router['TimeStamp']);
aggregate[router['Router']]["ReceivedBytes"]
.push(router['ReceivedBytes']);
aggregate[router['Router']]["TransferredBytes"]
.push(router['TransferredBytes']);
}

Related

Function returning object instead of Array, unable to .Map

I'm parsing an order feed to identify duplicate items bought and group them with a quantity for upload. However, when I try to map the resulting array, it's showing [object Object], which makes me think something's converting the return into an object rather than an array.
The function is as follows:
function compressedOrder (original) {
var compressed = [];
// make a copy of the input array
// first loop goes over every element
for (var i = 0; i < original.length; i++) {
var myCount = 1;
var a = new Object();
// loop over every element in the copy and see if it's the same
for (var w = i+1; w < original.length; w++) {
if (original[w] && original[i]) {
if (original[i].sku == original[w].sku) {
// increase amount of times duplicate is found
myCount++;
delete original[w];
}
}
}
if (original[i]) {
a.sku = original[i].sku;
a.price = original[i].price;
a.qtty = myCount;
compressed.push(a);
}
}
return compressed;
}
And the JS code calling that function is:
contents: compressedOrder(item.lineItems).map(indiv => ({
"id": indiv.sku,
"price": indiv.price,
"quantity": indiv.qtty
}))
The result is:
contents: [ [Object], [Object], [Object], [Object] ]
When I JSON.stringify() the output, I can see that it's pulling the correct info from the function, but I can't figure out how to get the calling function to pull it as an array that can then be mapped rather than as an object.
The correct output, which sits within a much larger feed that gets uploaded, should look like this:
contents:
[{"id":"sku1","price":17.50,"quantity":2},{"id":"sku2","price":27.30,"quantity":3}]
{It's probably something dead simple and obvious, but I've been breaking my head over this (much larger) programme till 4am this morning, so my head's probably not in the right place}
Turns out the code was correct all along, but I was running into a limitation of the console itself. I was able to verify this by simply working with the hard-coded values, and then querying the nested array separately.
Thanks anyway for your help and input everyone.
contents: compressedOrder(item.lineItems).map(indiv => ({
"id": indiv.sku,
"price": indiv.price,
"quantity": indiv.qtty
}))
In the code above the compressedOrder fucntion returns an array of objects where each object has sku, price and qtty attribute.
Further you are using a map on this array and returning an object again which has attributes id, price and quantity.
What do you expect from this.
Not sure what exactly solution you need but I've read your question and the comments, It looks like you need array of arrays as response.
So If I've understood your requirement correctly and you could use lodash then following piece of code might help you:
const _ = require('lodash');
const resp = [{key1:"value1"}, {key2:"value2"}].map(t => _.pairs(t));
console.log(resp);
P.S. It is assumed that compressedOrder response looks like array of objects.

How do I join separate json objects output from a for loop into an array?

I am scraping websites using CasperJS and one of the tasks involve crawling across url set by a for loop counter. The url looks like this
www.example.com/page/no=
where the no is any number from 0-10 set by the for loop counter. The scraper then goes through all the pages, scrapes the data into a JSON object and repeats until no=10.
The data that I am trying to get is stored in discrete groups in each page- what I would like to work with is a single JSON object by joining all the scraped output from each page.
Imagine Page1 has Expense 1 and the object I am getting is { expense1 } and Page 2 has Expense 2 and object that I am getting is { expense2 }. What I would like to have is one JSON at the end of scraping that looks like this:
scrapedData = {
"expense1": expense1,
"expense2": expense2,
}
What I am having trouble is joining all the JSON object into one array.
I initialized an empty array and then each object gets pushed to array.
I have tried a check where if iterator i in for loop is equal to 10, then the JSON object is printed out but that didnt seem to work. I looked up and it seems Object spread is an option but I am not sure how to use it this case.
Any pointers would be helpful. Should I be using any of the array functions like map?
casper.then(function(){
var url = "https:example.net/secure/SaFinShow?url=";
//We create a for loop to go open the urls
for (i=0; i<11; i++){
this.thenOpen(url+ i, function(response){
expense_amount = this.fetchText("td[headers='amount']");
Date = this.fetchText("td[headers='Date']");
Location = this.fetchText("td[headers='zipcode']");
id = this.fetchText("td[headers='id']");
singleExpense = {
"Expense_Amount": expense_amount,
"Date": Date,
"Location": Location,
"id": id
};
if (i ===10){
expenseArray.push(JSON.stringify(singleExpense, null, 2))
this.echo(expenseArray);
}
});
};
});
Taking your example and expanding on it, you should be able to do something like:
// Initialize empty object to hold all of the expenses
var scrapedData = {};
casper.then(function(){
var url = "https:example.net/secure/SaFinShow?url=";
//We create a for loop to go open the urls
for (i=0; i<11; i++){
this.thenOpen(url+ i, function(response){
expense_amount = this.fetchText("td[headers='amount']");
Date = this.fetchText("td[headers='Date']");
Location = this.fetchText("td[headers='zipcode']");
id = this.fetchText("td[headers='id']");
singleExpense = {
"Expense_Amount": expense_amount,
"Date": Date,
"Location": Location,
"id": id
};
// As we loop over each of the expenses add them to the object containing all of them
scrapedData['expense'+i] = singleExpense;
});
};
});
After this runs the scrapedData variable should be of the form:
scrapedData = {
"expense1": expense1,
"expense2": expense2
}
Updated code
One problem with the above code is that inside the for loop when you loop over the expenses, the variables should be local. The variable names also should not be Date and Location since those are built-in names in JavaScript.
// Initialize empty object to hold all of the expenses
var scrapedData = {};
casper.then(function(){
var url = "https:example.net/secure/SaFinShow?url=";
//We create a for loop to go open the urls
for (i=0; i<11; i++){
this.thenOpen(url+ i, function(response){
// Create our local variables to store data for this particular
// expense data
var expense_amount = this.fetchText("td[headers='amount']");
// Don't use `Date` it is a JS built-in name
var date = this.fetchText("td[headers='Date']");
// Don't use `Location` it is a JS built-in name
var location = this.fetchText("td[headers='zipcode']");
var id = this.fetchText("td[headers='id']");
singleExpense = {
"Expense_Amount": expense_amount,
"Date": date,
"Location": location,
"id": id
};
// As we loop over each of the expenses add them to the object containing all of them
scrapedData['expense'+i] = singleExpense;
});
};
});

delete user from json table in js

So I'm a beginner to js and I have a table of users in a json file and I'm making an account delete feature. I have a find set up to find the user and it works fine but I can't figure out how to make it delete the user from the file, any help would be appreciated!
Json:
{
"users": [
{
"name": "ImBattleDash",
"Id": "780748c5d4504446bbba3114ce48f6e9",
"discordId": "471621420162744342",
"dateAdded": 1548295371
}
]
}
JS:
function findJson() {
fs.readFile('./linkedusers.json', 'utf-8', function (err, data) {
if (err) message.channel.send('Invalid Code.')
var arrayOfObjects = JSON.parse(data)
let findEntry = arrayOfObjects.users.find(entry => entry.discordId == myCode)
let linkEmbed = new Discord.RichEmbed()
.setTitle('Account unlinked!')
.setDescription('Link your account by friending "BattleDash Bot" on Fortnite and then input the code you get messaged by typing "!link <code>"!')
.setColor('#a900ff');
message.channel.send({embed: linkEmbed});
})
}
EDIT: Not sure if it's an array or a table I don't know a lot about json
You need to use:
Array#find to find a given user by some given criteria.
Array#indexOf to get the index of the found user in users
Array#splice to drop one element starting from the index given by Array#indexOf:
const input = {
"users": [
{
"name": "ImBattleDash",
"Id": "780748c5d4504446bbba3114ce48f6e9",
"discordId": "471621420162744342",
"dateAdded": 1548295371
}
]
}
const removeUser = (criteria, users) =>
users.splice (users.indexOf (users.find (criteria)), 1)
removeUser (
({ Id, discordId }) =>
Id == '780748c5d4504446bbba3114ce48f6e9'
&& discordId == '471621420162744342',
input.users
)
// Output: 0 <-- User has been removed!
console.log(input.users.length)
About persisting the change, it's just about calling JSON.stringify (input) and then just write the contents to the desired output file. See this other Q&A: Writing files in Node.js
With great help from Cat and Matias I came up with this code that works!
function findJson() {
fs.readFile('./linkedusers.json', 'utf-8', function (err, data) {
if (err) message.channel.send('Invalid Code.')
var arrayOfObjects = JSON.parse(data)
let findEntry = arrayOfObjects.users.find(entry => entry.discordId == myCode)
const input = arrayOfObjects;
const removeUser = (criteria, users) =>
users.splice (users.indexOf (users.find (criteria)), 1)
removeUser (
({ Id, discordId }) =>
Id == findEntry.Id
&& discordId == findEntry.discordId,
input.users
)
console.log('unlinked')
fs.writeFile('./linkedusers.json', JSON.stringify(arrayOfObjects, null, 4), 'utf-8', function(err) {
if (err) throw err
console.log('Done!')
})
let linkEmbed = new Discord.RichEmbed()
.setTitle('Account unlinked!')
.setDescription('Link your account by friending "BattleDash Bot" on Fortnite and then input the code you get messaged by typing "!link <code>"!')
.setColor('#a900ff');
message.channel.send({embed: linkEmbed});
})
}
Here's a quick tutorial for you:
"Users" would be either an array (using []) or a javascript object (using {}), your choice. There won't be any actual tables unless you use a database instead of a JSON file (although if your JSON expression is as simple as your example, you could almost think of it as a table.) -- And actually, a third option would be to use the javascript Map type, which is like a beefed-up object, but I won't address that here.
While using an array would make it a bit easier to retrieve a list of data for all users (because arrays are simpler to iterate through), using an object would make it considerably easier to retrieve data for a single user (since you can directly specify the user you want by its key instead of needing to loop through the whole array until you find the one you want.) I'll show you an example that uses an object.
The individual user in your sample code is an example of a javascript object. JSON lets you convert an object to a string (for storage, I/O, and human readability) and back to an object (so javascript can understand it). You use the JSON.stringify() and JSON.parse() methods, respectively for these conversions. The string has to be JSON-formatted or this won't work, and your example is almost in JSON format.
To comply with JSON formatting, you could structure a Users object as follows. (Of course we're looking at the stringified version because mere humans can't easily read an "actual" javascript object):
"Users": { // Each individual user is a property of your users object
"780748c5d4504446bbba3114ce48f6e9": // The Id is the key in the "key/value pair"
{ // The individual user object itself is the value in the key/value pair
// Id is duplicated inside user for convenience (not necessarily the best way to do it)
"id": "780748c5d4504446bbba3114ce48f6e9",
"name": "ImBattleDash", // Each property of the user is also a key/value pair
"discordId": "471621420162744342", //Commas separate the properties of an object
"dateAdded": "1548295371" // All property values need double quotes for JSON compatibility
}, // Commas separate the properties (ie the individual users) of the users object
"446bbba3114ce48f6e9780748c5d4504": // This string is the second user's key
{ // This object is the second user's value
"id": "446bbba3114ce48f6e9780748c5d4504",
"name": "Wigwam",
"discordId": "162744342471621420",
"dateAdded": "1548295999"
}
}
Once you retrieve the string from storage, you convert it to an object and delete a user as follows. (This is broken down into more steps than necessary for clarity.):
let usersObject = JSON.parse(stringRetrievedFromFile);
let userId = "780748c5d4504446bbba3114ce48f6e9";
let userToModifyOrDelete = usersObject[userId];
delete userToModifyOrDelete;
To change the user's discordId instead, you would do:
let discordId = userToModifyOrDelete.discordId; // Not necessary, just shows how to retrieve value
let newDiscordId = "whateverId";
userToModifyOrDelete.discordId = newDiscordId;
And you'd convert the object back into a string to store in your file with:
JSON.stringify(usersObject);
Hopefully that's almost all you need to know about JSON!

Returning a unique value across documents in couchDB usings views

I have a series of documents each containing a date and a list of letters. I need the output to be a single, unique letter per key with the latest date for each letter as a value.
With a simple mapping function that looks like:
{
"_id": "_design/output",
"_rev": "1-c7b904b0e93709113c49127efb40187a",
"language": "javascript",
"views": {
"output": {
"map": "function(doc) {\n emit(doc.args.report.updated_partitions, doc.timestamp);\n}",
"reduce": "function(key, value, reduce) {\n return (value)\n}"
}
}
}
I get the following result:
{"total_rows":2,"offset":0,"rows":[
{"id":"8e561dd15fd33acfc7c4502c58008c2a","key":["a","b"],"value":1403818824},
{"id":"8e561dd15fd33acfc7c4502c5800a212","key":["a","c","d"],"value":1403818700}
]}
The output I'm looking for should look like:
{"total_rows":2,"offset":0,"rows":[
{"id":"8e561dd15fd33acfc7c4502c58008c2a","key":["a"],"value":1403818824},
{"id":"8e561dd15fd33acfc7c4502c58008c2a","key":["b"],"value":1403818824},
{"id":"8e561dd15fd33acfc7c4502c58008c2a","key":["c"],"value":1403818824},
{"id":"8e561dd15fd33acfc7c4502c5800a212","key":["d"],"value":1403818700}
]}
I actually found a simpler method. The basic steps are:
Map each individual letter to the date
Reduce the result by returning the maximum value from an array of all dates by key.
The map looks like:
function(doc) {
var files = doc.args.report.updated_partitions;
var timestamp = doc.timestamp;
for (i=0; i<files.length; i+= 1){
var file_name = files[i];
emit(file_name, timestamp);
}
}
And the reduce looks like:
function(key, value, reduce) {
return (Math.max.apply(null, value))
}
The result will be a unique key for each letter with the latest date from all docs as a value.
The use case for this is when each couch document has a list of files that were modified and the date the modification took place, but you would like to know the latest modification date for each individual document.

Load JSON array from a database SQLITE

I have the following code in an array for Javascript JSON:
params = {
"fighters": [
{
"name": "Muhammad Ali",
"nickname": "The Greatest"
},
{
"name": "Chuck Liddell",
"nickname": "The Iceman"
}
]
};
Now I have "N" variable data "name" and "nickname" from a database SQLITE.
The idea is to show all the "nick" and "nickname" that exist from the database iteratively.
How I can fill it?
I tested with a FOR that runs all the arrangements and I charge them, for it did something like this:
params = {
"fighters": [ show[i] ]
};
It does not work.
I hope I explained correctly.
Thanks.
That will retrieve all fighters names:
var len = params.fighters.length;
for (var i = 0; i < len; i++) {
console.log( params.fighters[i].name );
}
To change fighters names values do the following:
var len = params.fighters.length;
for (var i = 0; i < len; i++) {
params.fighters[i].name = 'Your_Fighter_Name';
}
Hopefully i have helped you.
assuming we're in the fetchAll(function (error, rows) {}) callback using node-sqlite (meaning rows is an array of objects, with the keys in the objects being the column names):
var params = { "fighters" : [] };
rows.forEach(function (row) {
params.fighters.push({name: row.name, nickname: row.nickname});
});
Remember, JSON is subset of JS, it is not it's own language. It's NOT a programming language. You can't "do" anything in JSON, as it is not a programming language. You can't iterate, recurse, fill... you can do that with JS.
Sorry for repeating myself, but apparently a lot of people mistake JSON for something it isn't. I'm not assuming you do, but it can't be said too often ;-) How you want to send the JSON I can't tell you, as there is no information in your question. If you want to do this via a byte-based protocol such as HTTP you might want to use JSON.stringify() to get a textual representation of your object that you can send over the network.
See my version of your fiddle: http://jsfiddle.net/dpL4c/2/ .

Categories

Resources