Get Data from parsed XML to JSON - javascript

I'm trying to get some data from a parsed XML to JSON but now I'm stuck and not be able to get the data. Could someone show me how to get the data in the right way to show on my screen?
Formatted JSON Data
{
"event":[
{
"name":"Queen",
"date":"2019-09-12",
"genre":"rock",
"time":"20:00:00",
},
{
"name":"2Pac",
"date":"2019-09-25",
"genre":"rap",
"time":"20:00:00"
},
data () {
return {
result: null
}
},
created () {
this.getConcertData()
},
methods: {
getConcertData () {
const parseString = require('xml2js').parseString
this.$axios.get('members.php?xml')
.then((response) => {
const self = this
parseString(response.data, function (err, result) {
self.events = result
console.log(result)
})
})
}
}

You can try to confirm if you have successfully obtained the expected format data(use developer tools or just log the response.data),
then make sure require('xml2js').parseString work well.

Related

Filter API response directly in URL

I would like to know if it is possible to filter the response of an API directly via the URL.
URL API : https://coronavirus-19-api.herokuapp.com/countries
I only put 2 countries for the example but the structure of the answer is like this:
[
{
"country":"USA",
"cases":176518,
"todayCases":12730,
"deaths":3431,
"todayDeaths":290,
"recovered":6241,
"active":166846,
"critical":3893,
"casesPerOneMillion":533,
"deathsPerOneMillion":10,
"firstCase":"\nJan 20 "
},
{
"country":"Italy",
"cases":105792,
"todayCases":4053,
"deaths":12428,
"todayDeaths":837,
"recovered":15729,
"active":77635,
"critical":4023,
"casesPerOneMillion":1750,
"deathsPerOneMillion":206,
"firstCase":"\nJan 29 "
}
]
For the moment in my project I collect all the responses and I filter afterwards to have only the data for a country but to optimize performance I would like to filter the responses directly by URL.
async getCountryStats() {
try {
let response = await fetch("https://coronavirus-19-api.herokuapp.com/countries")
if (response.status === 200) {
let data = await response.json()
// Data object with ID
data = Object.assign({}, data)
// Data object with name of property
let obj = {}
for (let i in data) {
obj = { ...obj, [data[i].country]: data[i] }
}
this.setState({ focusStats: obj[this.state.focusCountry] })
} else {
this.setState({ errorStatus: true })
console.error('Error status')
}
} catch (err) {
console.error(err)
}
}
I use React, here is my repository: https://github.com/michaelbaud/covid19, here is the rendering: https://suspicious-kilby-d90f99.netlify.com
You can use the following link instead:
https://coronavirus-19-api.herokuapp.com/countries/{country-name}
For example in your case it would be:
USA : https://coronavirus-19-api.herokuapp.com/countries/USA
Italy : https://coronavirus-19-api.herokuapp.com/countries/italy
Good Luck

Unable to get information from Array

```
function displayResults(responseJson) {
const gamedata = responseJson.results.map(game => {
return {
name: game.name,
consoles: game.platforms,
metacritc: game.metacritic,
genre: game.genres
};
});
console.log(gamedata);
inputData(gamedata);
}
function platformdata(consoles) {
return consoles.map(system => {
return system.platform.name;
});
}
function inputData(gamedata) {
gamedata.map(input => {
$(`#home-list`).html(`
<h1>${input.name}</h1>
<h5>${input.metacritc}</h5>
<span>${input.system}</span>
`);
});
}
```
I have been trying to get information from an array but have not been successful in obtaining the information. The information for the game platforms is somewhat nested and I have been trying to dig it out but to no avail.
https://api.rawg.io/api/games?page_size=1
Best way I can show the information more in detail is to just advise to throw the link above into postman and you'll see what I am trying to work with. Basically it is under results > platforms > platform > name. When I add this information into the map function it comes up undefined. Running it now they come up with saying object with commas. I'd like it to just come up with just the information leaving out the commas. I can't figure out how to get join() to go into html(). Thank you very much!
Edit:
1) Results I'd like is to be able to pull up is within the platforms tree but is buried. If I just use game.platforms it produces [object, Object]. If I try to add more to the line in gamedata it will produce undefined.
2) In "gamedata.map(input => {" ?
3) Yes I tried making a helper function based on code I found online. The code I found online used excessive li and ul
```
function platformnames(platforms) {
return platforms.map(system => {
return '<li>' system.platform.name + '</li>';
});
}
function pullArray(gamedata) {
gamedata.map(function(input) {
let platformNames = input.platforms.map(
system => `<li>${system.platform.name}</li>`
);
$(`#home-container`)
.append(`<li><ul><li>${platformNames}</li></ul></li>`)
.join(' ');
});
}
```
This worked but gave really odd results.
4) No I'm adding it all to the same ID as one pull.
5) That is me trying to mine the information from platforms on an API. It's buried in there and I haven't found a good solution.
function formatParams(params) {
const queryItems = Object.keys(params).map(
key => `${key}=${params[key]}`
);
console.log(queryItems);
return queryItems.join('&');
}
const opts = {
headers: {
'User-Agent': `<ClassProject> / <VER 0.01> <Currently in Alpha testing>`
}
};
function fetchAPI() {
const params = {
...($('.search-param').val() && {
search: $('.search-param').val()
}),
...($('.genre-param').val() && {
genres: $('.genre-param').val()
}),
...($('.platforms-param').val() && {
platforms: $('.platforms-param').val()
}),
...($('.publishers-param').val() && {
publishers: $('.publishers-param').val()
}),
page_size: '1'
};
console.log(params);
const baseURL = 'https://api.rawg.io/api/games';
const queryString = formatParams(params);
let url = `${baseURL}?${queryString}`;
console.log(url);
fetch(`${url}`, opts)
.then(response => response.json())
.then(responseJson => displayResults(responseJson))
.catch(error => {
console.log(`Something went wrong: ${error.message}`);
});
}
function displayResults(responseJson) {
const gamedata = responseJson.results.map(game => {
return {
name: game.name,
consoles: game.platforms,
metacritc: game.metacritic,
genre: game.genres
};
});
console.log(gamedata);
inputData(gamedata);
}
function inputData(gamedata) {
let html = '';
gamedata.forEach(input => {
html += `<h1>${input.name}</h1>`;
html += `<h5>Metacritic: ${input.metacritic ||
'No metacritic rating'}</h5>`;
html += 'Platforms:<br />';
input.consoles.forEach(e => {
html += `<span>${e.platform.name}</span><br />`;
});
html += `<br /><span>System: ${input.system}</span>`;
});
document.getElementById('home-list').innerHTML = html;
}
function pageLoad() {
$(document).ready(function() {
fetchAPI();
});
}
pageLoad();
So I'm close thanks to the help of everyone here. Now I'm returning "Metacritic: No metacritic rating" or if I remove that or part an undefined. What am I missing?
The snippet below gets you the platform names. I modified/created
the displayResults() function to only return a value (and also corrected the typo in metacritic (metacritc -> metacritic))
the inputData() function to create a correct HTML and append it to the container
a fetchData() function to actually fetch the data
an unnamed function to initiate fetch and display the data
You should look at your data - you don't use game.genres (although you map it) and you would like to display input.system that is not mapped.
function displayResults(responseJson) {
return responseJson.results.map(game => {
return {
name: game.name,
consoles: game.platforms,
metacritic: game.metacritic,
genre: game.genres
};
});
}
function platformdata(consoles) {
return consoles.map(system => {
return system.platform.name;
});
}
function inputData(gamedata) {
let html = ''
gamedata.forEach(input => {
html += `<h1>${input.name}</h1>`
html += `<h5>Metacritic: ${input.metacritic || 'No metacritic rating'}</h5>`
html += 'Platforms:<br />'
input.consoles.forEach(e => {
html += `<span>${e.platform.name}</span><br />`
})
html += `<br /><span>System: ${input.system}</span>`
});
document.getElementById('home-list').innerHTML = html
}
async function fetchData() {
const data = await fetch('https://api.rawg.io/api/games?page_size=5')
const json = await data.json()
return json
}
(async function() {
const json = await fetchData()
inputData(displayResults(json))
})();
<div id="home-list"></div>
And although it does work - you're not supposed to use more than one h1 tag on a site - it will be an HTML validation warning (SEO!). If you will display only one game per page, then forget my remark :)

Promise.resolve() return only one element in nested array

Here is my code:
search(): Promise<MyModel[]> {
const query = {
'action': 'update',
};
return new Promise((resolve, reject) => {
this.api.apiGet(`${API.SEARCH_STUDENT}`, query).then((data) => {
const a = data.items.map(i => i);
const b = data.items.map(i => i);
console.log(a.array1[0].array2.length); // 1
console.log(b.array1[0].array2.length); // 5
resolve(a);
}, (error) => {
reject(error);
});
});
}
MyModel class:
class MyModel {
...
array1: [{
array2: []
}]
}
data.items[0].array1[0].array2 returned by function apiGet contains 5 elements. But if I put a or b into resolve function, it now just keep first element only like the comments in the snippet.
Could anyone show what I miss here?
Firstly I am not sure why you wrap a promise in a promise.. why do you need to do that when
this.api.apiGet returns a promise.
Also, why are you trying to map? I bet if you console.log(data.items) the same data would come back. I think you have just got a little confused with your code. A tidy up of the code should resolve all of this for you.
I would do something like the below, now every time you call search you get all the data back which you can use when you want it.
search(): Promise<MyModel[]> {
const query = {
'action': 'update',
};
return this.api.apiGet(API.SEARCH_STUDENT, query)
.then((data) => data as MyModel[]));
}

Conditional get request in vue for rendering a subcomponent scoped

When I click a profile (of an author) component, I can't figure out how it should render a scoped sub-component, listing the main entities of the app, so-called fabmoments (containers for 3D print information).
My current solution looks like this:
export default {
name: 'Multipe',
props: [
'author'
],
data () {
return {
// search: '',
localAuthor: '',
fabmoments: []
}
},
created () {
this.localAuthor = this.author
if (typeof localAuthor !== 'undefined') {
this.$http.get(`/users/${this.$route.params.id}/fabmoments`)
.then(request => this.buildFabmomentList(request.data))
.catch(() => { alert('Couldn\'t fetch faboments!') })
} else {
this.$http.get('/fabmoments')
.then(request => this.buildFabmomentList(request.data))
.catch(() => { alert('Couldn\'t fetch faboments!') })
}
},
methods: {
buildFabmomentList (data) {
this.fabmoments = data
}
},
components: {
// Box
}
}
This renders all in the profile, where it should render a list scoped to the current profile's author.
And it renders nothing in the home (without receiving the prop), where it should render all.
I am not much of star in JavaScript. What am I doing wrong?
UPDATE
This works as a solution, though not very elegant.
export default {
name: 'Multipe',
props: [
'author'
],
data () {
return {
fabmoments: []
}
},
created () {
if (this.author.id >= 0) {
this.$http.get(`/users/${this.$route.params.id}/fabmoments`)
.then(request => this.buildFabmomentList(request.data))
.catch(() => { alert('Couldn\'t fetch faboments!') })
} else {
this.$http.get('/fabmoments')
.then(request => this.buildFabmomentList(request.data))
.catch(() => { alert('Couldn\'t fetch faboments!') })
}
},
methods: {
buildFabmomentList (data) {
this.fabmoments = data
}
},
components: {
// Box
}
}
Not sure which part is wrong, but you may definitely debug your code to find out why fabmoments is empty array assuming there is no error occurred yet.
There are three parts to debug:
http response -- to check if data is properly returned
this -- to check if this pointer still points at the component
template -- to check if fabmoments are correctly bind to the element
At last, it would be better to separate your http request logics from your components.
Good luck!

How to push Object element to an array in Vuejs/Javascript

I'm trying to build a small application in VueJs,
Following is my data set:
data(){
return {
pusher: '',
channel:'',
notify: [],
notifications: '',
notificationsNumber: '',
}
},
where I'm having an axios call in created property of components as:
axios.get('api/notifications', {headers: getHeader()}).then(response => {
if(response.status === 200)
{
this.notify = response.data.notifications
this.notificationsNumber = this.notify.length
}
}).catch(errors => {
console.log(errors);
})
I'm having pusherJs implemented, so I'm having following code:
this.pusher = new Pusher('xxxxxxxx', {
cluster: 'ap2',
encrypted: true
});
var that = this
this.channel = this.pusher.subscribe('stellar_task');
this.channel.bind('company_info', function(data) {
console.log(data.notification);
that.notifications = data.notification
});
Once the value is being obtained from pusher I want to push this to my array notify as watch property, something like this:
watch: {
notifications(newValue) {
this.notify.push(newValue)
this.notificationsNumber = this.notificationsNumber + 1
}
}
So the problem is the data format which I'm receiving through pusher is in object form and push function is not getting implemented in this:
Screenshot:
Help me out with this.
I'm making an assumption that response.data.notifications is an Array Like Object.
So all you have to do is:
this.notify = [...response.data.notifications];

Categories

Resources