Mapping JSON to ES6 Classes - javascript

I have our staff in a json file, and had the idea to use that data with ES6 classes. The more I work with this, the more I feel as though I may be missing something. I had this working in coffeescript as such:
fetch = require('node-fetch')
domain = 'domain.com'
apiSrc = 'api.domain.com'
slug = 'people'
class Person
constructor: (json) -> {name: #name, title: #title, school: #school, bio: #bio} = json
email: (username) ->
username.replace(/\s/, '.').toLowerCase() + '#' + domain
profile: ->
content = []
if this.name then content.push("#{#name}")
if this.title then content.push("#{#title}")
if this.school then content.push(school) for school in "#{#school}"
if this.bio then content.push("#{#bio}")
if this.name then content.push(this.email("#{#name}"))
content.join('')
fetch('http://' + apiSrc + '/' + slug + '.json')
.then((response) -> response.json())
.then((api) ->
content = []
group = []
group.push(new Person(them)) for them in api[slug]
for them, index in group
content.push(them.profile())
console.log(content.join(''))
)
But then I thought it would be even better if I could convert it to ES6. I know the use case is simple, and classes certainly aren't necessary, since I'm just using the data for templating, however, for the sake of learning, I was attempt to do this. Am I going about this the wrong way? Right now, I feel like there should be a way to return all of the "people" that I put into the Person class. However, the only way I could figure out how to do that was to run a for loop and then write it to the document.
class Person {
constructor(data) { ({name: this.name, title: this.title, school: this.school, bio: this.bio, email: email(this.name)} = data); }
email(username) {
return username.replace(/\s/, '.').toLowerCase() + '#' + location.hostname.replace(/[^\.\/\#]+\.[^\.\/]+$/, '');
}
profile() {
return `${this.name} ${this.title}`;
}
}
var apiSrc = 'api.domain.com';
var slug = 'people';
fetch(`http://${apiSrc}/${slug}.json`)
.then(function(response) { return response.json() }) // .then(response => response.json())
.then(function(api) {
var content = [];
var group = [];
for (var i = 0; i < api[slug].length; i++) { var them = api[slug][i]; new Person(them); }
for (var i = 0; index < group.length; i++) {
var them = group[i];
content.push(them.profile());
console.log(content.join(''));
}
});
My ES6 conversion actually isn't even working right now. API returns the JSON but after that it gets messed up. Any suggestions would be really helpful as I'm trying to better myself as a coder and hope this sort of example could help others learn Classes in a real use case.

You might try using the reviver parameter of JSON.parse. Here is a simplified example:
class Person {
// Destructure the JSON object into the parameters with defaults
constructor ({name, title, school=[]}) {
this.name = name
this.title = title
this.school = school
}
}
var api = JSON.parse(a, function (k,v) {
// Is this a new object being pushed into the top-level array?
if (Array.isArray(this) && v.name) {
return new Person(v)
}
return v
})
var group = api["people/administration"]

Related

How do I console.log json information?

quite new to working with both api's and javascript. I'm trying to console.log out the amount of times a friend of mine has died in rust, but all items are named "name:" An img of what I mean:
I'm using axios to call the api, here's the code:
var statsApi = 'http://api.steampowered.com/ISteamUserStats/GetUserStatsForGame/v0002/?';
var statsAppId = 'appid='+252490+'&'
var statsSteamApiKey = 'key='+process.env.STEAM_API+'&';
var statsUserArg = 'steamid='+userID;
var steamStatsApi = statsApi + statsAppId + statsSteamApiKey + statsUserArg;
axios
.get(steamStatsApi)
.then((res) =>{
message.channel.send("AAAA");
// console.log(res['data']['playerstats']['stats']['name' == 'deaths']);
for(re in res['data']['playerstats']['stats']) {
if(re['name'] === 'deaths') {
console.log('test');
console.log(re['value']);
}
else {
console.log('Fel');
}
}
})
.catch((err) => {
console.error('Error:', err);
})
Again if anyone knows how to get the amount of 'deaths' I'd be super grateful.
Turns out it was quite easy, if anyone has this problem just use the following code which I am about to provide:
var index = -1;
for(var i = 0; i < Object.keys(res['data']['playerstats']['stats']).length; i++) {
if(res['data']['playerstats']['stats'][i]['name'] === 'deaths') {
index = i;
var userDeaths = res['data']['playerstats']['stats'][index]['value'];
break;
}
}
What this does is that it loops trough every object named "name:" until it finds 'deaths' in one of them. I change i to that and now i'm able to print out the value which i'm looking for.
Please check this code:
let res = [{ name: "deaths", value: 2694}, {name:"bullet_fired", value: 343328}];
let i = 0;
for(i=0;i<res.length;i++){
if(res[i].name =="deaths"){
console.log(res[i].value);
}
}
Here res variable will contain your json values.

Creating a JS object

I am working with the Wordpress REST API to retrieve some tags from a website. Maybe I haven't searched for the correctly on SO, but I am trying to get use my data and create my dataSet variable. But I am getting an error saying it's not recognizing the for loop token. I am quite new to Javascript so I don't know how to fix this.
Here is my code:
var req = new XMLHttpRequest();
var pieChart = document.getElementById('pie_chart_1');
req.open("GET", "http://example.org/wp-json/wp/v2/tags?per_page=10")
req.onload = function() {
if (req.status >= 200 && req.status < 400) {
var data = JSON.parse(req.responseText);
} else {
console.log("Returning an error");
}
};
req.onerror = function() {
console.log("Connection error");
};
req.send();
var dataSet = [
for(i = 0; i < data.length; i++) {
{legendLabel: data[i].name, magnitude:data[i].count, link: "http://example.com/tag" + data[i].slug},
}
];
You have a for loop inside the square brackets to define an array which is not syntactically correct. Since you are fetching tags using the WordPress REST API the response will be a JSON object with a tags property containing the results. It looks like you have a missing / in your link value as well.
Assuming this value for data.tags -
[{
display_name: 'Test Name',
slug: 'test-name',
}];
To properly use a for loop for this purpose -
const dataSet = [];
const tags = data.tags;
for (let i=0; i<tags.length; i+=1) {
dataSet.push({
legendLabel: tags[i].display_name,
link: "http://example.com/tag" + tags[i].slug,
});
}
A better way to create an array of JSON objects from your original array of JSON objects is to use Array.map() to "map" each element in the first array to a new element in a new array -
const dataSet = data.tags.map(function (element) {
return {
legendLabel: element.display_name,
link: "http://example.com/tag/" + element.slug,
};
});
Taking it further, you can use an arrow function, object parameter deconstruction, explicit return, string patterns, etc for more compact syntax with the same functionality -
const dataSet = data.tags.map(({ display_name: displayName, slug }) => ({
legendLabel: displayName,
link: `http://example.com/tag/${slug}`,
});
First of all, in most cases, it is better to use fetch API
In JS there is no for comprehensions so the last block of code could be refactored as follows:
const dataSet = data.map(({ name, count, slug }) => ({
legendLabel: name,
magnitude: count,
link: `http://example.com/tag${slug}`
}));

Meteor: Underscore _findWhere iteration through loop objects only works in chrome console, in app it says undefined

I'm trying to fetch an object 'single Post' within an object 'Posts' from a json file within meteor, which looks like this.
I found an effective way of doing it, using underscore findWhere to get to it. this is the code
_.findWhere(_.findWhere(CategoryCollection.find().fetch(),
{"_id":"CategoryPublication-5"}).posts,{"ID":46});
however when i put this into meteor, i'm getting undefined
this is the code i used
Template.CategoryArticleSingle.helpers({
articles: function () {
var id = FlowRouter.getParam('ID')
var category = FlowRouter.getParam('category')
console.log(CategoryCollection.find().fetch());
let match = _.findWhere(_.findWhere(CategoryCollection.find().fetch(), {"_id":category}).posts,{"ID": id});
console.log("match",id,category,match);
return match;
}
});
Why am i getting undefined
update.
would this be correct? i substituted the 47 id, with just id so i can use it for any link.
Im getting "category" is read-only error.
Template.CategoryArticleSingle.helpers({
articles: function () {
var id = FlowRouter.getParam('ID')
var category = FlowRouter.getParam('category')
console.log(CategoryCollection.find().fetch());
const category = CategoryCollection.find().fetch().find(c => c._id === id);
let post = null;
if (category) {
post = category.posts.find(p => p.ID === id);
}
console.log("post",id,category,post);
return post;
}
});
There's no need to use lodash/underscore's findWhere. This functionality is built into ES2015. Also, you may consider breaking up the code into a few lines to make it more legible.
const category = CategoryCollection.find().fetch().find(c => c._id === 'CategoryPublication-5');
let post = null;
if (category) {
post = category.posts.find(p => p.ID === 47);
}

Filter Return of Meteor FindOne?

How would I go about filtering the return of a FindOne function in Iron Router? I assume that aggregation is out of the question, but I may be wrong. I've tried many different ways that don't work. I'd like to return the id, name, and the season object that it finds a matching season_number in.
My database is setup like so:
_id
name
seasons (array)
season (object)
season_number
episodes (array)
episode (object)
episode_title
episode_number
Here's my iron router code that is currently just running a findOne function.
Router.route('/show/:_id/season/:season_number', {
name: 'viewSeasonPage', // This links to the template
data: function() { return Tv.findOne({_id:"KQBXq4nri7zssDna2", "seasons.season_number": 2}))}
});
Router.route('/show/:_id/season/:season_number', {
name: 'viewSeasonPage', // This links to the template
data: function() {
let tv = Tv.findOne({_id:"KQBXq4nri7zssDna2", "seasons.season_number": 2});
if (tv && tv.seasons) { return tv.seasons.find(function(season) { return season.season_number == 2; })
}
});
You need to filter the result to create the data object you want to return with the information you need. If your search doesn't find anything, your data is an empty object.
Router.route('/show/:_id/season/:season_number', {
name: 'viewSeasonPage',
data: function() {
// Find your object
var tv = Tv.findOne({
_id: this.params._id,
seasons: {
$elemMatch: {
season_number: this.params.season_number
}
}
});
// Fill data by filtering the correct season
var data = {};
if (tv) {
data._id = tv._id; // 1. ID
data.name = tv.name; // 2. NAME
// Find correct season in array
var season;
for (var i = tv.seasons.length - 1; i >= 0; i--) {
season = tv.seasons[i];
if (season.season_number == this.params.season_number) {
data.season = season; // 3. SEASON
}
};
}
return data;
}
});
I know it's a lot of coding, but this is for understanding the idea and the process.

How safe is sending in functions to String.replace?

I am writing a string resolver function and I want it to take an object to resolve all "<%=variable%>" occurrences. I have the ability to set some of the object properties to functions and have those functions return values automatically. Is this safe? I originally planned on parsing out the tokens and getting return values from functions based on what I parsed from the token. Having String.replace do it seems a lot easier but I am not sure what the security risks are. Any ideas or comments? This will mainly be used in node.js so I don't imagine any user access to the function.
var data = {
name: "Mike",
job: "programmer"
},
funcs = {
date: function () {return new Date;},
timestamp: function () {return new Date().getTime();},
guid: function () {return "4FGGX3g";}
};
function resolve (str,resolvers) {
var regex,result;
result = str;
str.match(/(<%=.+?%>)/g).forEach(function (item) {
var token,itr,resolver;
token = item.split(/(\w+)/)[1];
for (itr = 0; itr < resolvers.length; itr += 1) {
resolver = resolvers[itr][token];
if (resolver) {
regex = new RegExp(item,'g');
result = result.replace(regex,resolver);
break;
}
}
});
return result;
}
console.log(resolve("My name is <%=name%> and I am a <%=job%>.\nThe date is: <%=date%>\nTimestamp: <%=timestamp%>\nUniqieID: <%=guid%>",[data,funcs]));

Categories

Resources