Openweathermap API call responding with wrong json - javascript

I am using the hourly forecast API call from Openweathe map to build a weather app. I can correctly fetch the URL for the call but the structure of the JSON that shows seems not to match the one provided as an example. I can't access data.list or either data.sys or data.city.name. While I can access data.name.
Here is the example JSON
{
cod: "200",
message: 0.0208,
cnt: 96,
list: [
{
dt: 1553709600,
main: {
temp: 286.44,
temp_min: 286.258,
temp_max: 286.44,
pressure: 1015.82,
sea_level: 1015.82,
grnd_level: 1002.193,
humidity: 100,
temp_kf: 0.18
},
weather: [
{
id: 500,
main: "Rain",
description: "light rain",
icon: "10d"
}
],
clouds: {
all: 86
},
wind: {
speed: 5.51,
deg: 202.816
},
rain: {
1h: 0.812
},
sys: {
pod: "d"
},
dt_txt: "2019-03-27 18:00:00"
},
...
],
city: {
id: 420006353,
name: "Mountain View",
coord: {
lat: 37.3894,
lon: -122.0833
},
country: "US"
}
}
and here is the code I use to manage the call
function call(city,country,zip) {
let countryCode = list.getCode(country);
let API;
if (city!="" && country!="") {
API = 'http://api.openweathermap.org/data/2.5/weather?q='+city.toLowerCase()+','+countryCode.toLowerCase()+'&APPID=1a9b84b61d1a8d6fdbb52fa2800ef894';
}
else if(country!="" && zip!=""){
API ='http://api.openweathermap.org/data/2.5/forecast/hourly?zip='+zip.toString()+','+countryCode.toLowerCase()+'&APPID=1a9b84b61d1a8d6fdbb52fa2800ef894';
}
else{
alert("Please type your city or Zip code");
}
return API;
}
function getPlace() {
let city = cityInput.value;
let country = countryInput.value;
let zip = zipInput.value;
let APICall=call(city,country,zip);
fetch(APICall).then(response=>{
return response.json();
}).then(data=>{
let cityName= data.name;
settler(cityName);
})
}
I should be able to access data.list but
alert(data.list.lenght) gives me an error saying that can not define length of undefined. Same for alert(data.city.name) that says that can not access name property of undefined.

The weather API docs correctly show the data you should expect for weather query:
https://openweathermap.org/current
Your hourly query should work if you hit the correct endpoint (pro) which your (exposed; you should fix that) API key is not valid for (AFAICT).
The pricing page indicates that hourly data is not available for free.

Related

How can I format an excel file with empty rows to have nested arrays and match a JSON object that I need to render?

I am facing an issue with an excel file. I receive some data from the DB and the user should be able to replace that data with a spreadsheet that looks like this:
This is how the data comes from the DB and how the excel file should be finally formatted:
"employers": [{
"id": "4147199311345513",
"shifts": [{
"url": "https://zoom.com/983493unsdkd/",
"days": "Mon,Tue,Wed,Thu,Fri",
"name": "Morning",
"endTime": "12:00",
"timezone": "CST",
"startTime": "8:00"
}, {
"url": "https://zoom.com/983493unsdkd/",
"days": "Mon,Tue,Wed,Thu,Fri",
"name": "Afternoon",
"endTime": "12:00",
"timezone": "CST",
"startTime": "8:00"
}],
"employerUrl": "http://www.google.com",
"employerName": "AT&T",
"employerUrlText": "URL Text",
"employerLogoSmall": "assets/images/att-logo.png",
"employerDescription": "AT&T is a world premier employer with a bunch of stuff here and there."
}, {
"id": "3763171269270198",
"shifts": [{
"url": "https://zoom.com/983493unsdkd/",
"days": "Mon,Tue,Wed,Thu,Fri",
"name": "Morning",
"endTime": "12:00",
"timezone": "CST",
"startTime": "8:00"
}, {
"url": "https://zoom.com/983493unsdkd/",
"days": "Mon,Tue,Wed,Thu,Fri",
"name": "Afternoon",
"endTime": "12:00",
"timezone": "CST",
"startTime": "8:00"
}],
"employerUrl": "http://www.google.com",
"employerName": "AT&T",
"employerUrlText": "URL Text",
"employerLogoSmall": "assets/images/att-logo.png",
"employerDescription": "AT&T is a world premier employer with a bunch of stuff here and there."
}]
So I need to take that spreadsheet and format it to look like that JSON above. All of this with Javascript/React.
This is what I have so far to format my excel file and render it:
const [excelData, setExcelData] = useState({ rows: [], fileName: "" });
const fileHandler = (event) => {
let fileObj = event.target.files[0];
ExcelRenderer(fileObj, (err, resp) => {
if (err) {
console.log(err);
} else {
let newRows = [];
let shiftRows = [];
console.log(resp.rows);
resp.rows.slice(1).map((row, index) => {
if (row && row !== "undefined") {
return newRows.push({
key: index,
employer: {
name: row[0],
description: row[1],
employerUrl: row[2],
employerUrlText: row[3],
shifts: shiftRows.push({ shift: row[2] }),
},
});
}
return false;
});
setExcelData({ rows: newRows, fileName: fileObj.name });
}
});
};
That console.log above (console.log(resp.rows)) returns this:
Where the first row are the headers of the excel file.
And the code above ends up like this and it should be exactly as the JSON I mentioned:
rows: [
{
key: 0,
employer: {
name: 'AT&T',
description: 'AT&T is a world premier employer with a bunch of stuff here and there.',
shifts: 1
}
},
{
key: 1,
employer: {
shifts: 2
}
},
{
key: 2,
employer: {
shifts: 3
}
},
{
key: 3,
employer: {
shifts: 4
}
},
{
key: 4,
employer: {
name: 'Verizon',
description: 'Verizon is a world premier employer with a bunch of stuff here and there.',
shifts: 5
}
},
{
key: 5,
employer: {
shifts: 6
}
},
{
key: 6,
employer: {
shifts: 7
}
},
{
key: 7,
employer: {
shifts: 8
}
}
],
fileName: 'EmployerChats.xlsx',
false: {
rows: [
{
url: 'https://www.youtube.com/kdfjkdjfieht/',
title: 'This is a video',
thumbnail: '/assets/images/pages/5/links/0/link.png',
description: 'This is some text'
},
{
url: 'https://www.youtube.com/kdfjkdjfieht/',
title: 'This is a video',
thumbnail: '/assets/images/pages/5/links/1/link.png',
description: 'This is some text'
}
]
},
I am using this plugin to help me render the excel file: https://www.npmjs.com/package/react-excel-renderer
Any ideas on what can I do to make format the spreadsheet data as the JSON?
Please notice those empty rows.
For example every time there is a new employer name, that's a new row or item in the array, then all of the columns and rows below and after Shift Name is a new nested array of objects. Hence, this file contains an array with a length of 2 and then it contains another array of items when it hits the Shift Name column.
Is it clear?
1st of all - you don't need to follow 'original', class based setState. In FC you can just use two separate useState.
const [rows, setRows] = useState([]);
const [fileName, setFileName] = useState("");
Data conversion
I know that you need a bit different workflow, but this can be usefull (common point - data structure), too - as conversion guide, read on.
You don't need to use ExcelRenderer to operate on data from db and render it as sheet. Converted data can be exported to file later.
You can just create array of array (aoa) that follows expected view (rows = array of row cells array). To do this you need very easy algorithm:
let newData = []
map over emplyers, for each (emp):
set flag let first = true;
map over shifts, for each (shift):
if( first ) { newData.push( [emp.name, emp.descr, shift.name, shift.timezone...]); first = false;
} else newData.push( [null, null, shift.name, shift.timezone...]);
setRows( newData );
Rendering
<OutTable/> operates on data and colums props - structures similar to internal state. 'datais ourrows, we only needcolumns` prop, just another state value:
const [columns, setColumns] = useState([
{ name: "Employer name", key: 0 },
{ name: "Employer description", key: 1 },
{ name: "Shift name", key: 2 },
// ...
]);
and finally we can render it
return (
<OutTable data={rows] columns />
Later
User can operate on sheet view - f.e. insert rows using setRows() or download this as file (XLSX.writeFile()) after simple conversion:
var ws = XLSX.utils.aoa_to_sheet( columns.concat( rows ) );
There is a lot of utils you can use for conversions - see samples.
Back to your needs
We have data loaded from db, data in aoa form, rendered as sheet. I don't fully understand format you need, but for your db format conversion is simple (opposite to above) - you can follow it and adjust to your needs.
let newEmployers = [];
let empCounter = -1;
// itarate on rows, on each (`row`):
rows.map( (row) => {
// new employer
if( row[0] ) {
newEmployers.push( {
// id should be here
"employerName": row[0],
"employerDescription": row[1],
"shifts": [
{
"shiftName": row[3],
"shiftDescription": row[4],
// ...
}
]
} );
empCounter ++;
} else {
// new shift for current employer
newEmployers[empCounter].shifts.push(
{
"shiftName": row[3],
"shiftDescription": row[4],
// ...
}
);
}
});
// newEmployers can be sent to backend (as json) to update DB

How to send filters to an api with javascript

I have a catalog list with a 'favorite' option. Now I'm trying to make a watchlist that only shows the selected favorites. The data comes from the same api, but now for the watchlist I need to filter the api data to only show the favorites.
This is the code
"watchlist": {
cols: 5,
promise: function() {
return $.api("/catalog", {
count: 4,
}).then(
function(result) {
$(".dashboardpage .widget-watchlist").render('pages/dashboard/widget-watchlist', {
watchlist: result.data
}).animo("enterContent");
},
function(err) {
$(".dashboardpage .widget-watchlist").render('pages/dashboard/widget-watchlist', {
watchlist: [],
error: err
}).animo("enterContent");
}
);
}
},
This is the JSON data
data: [{score: 4, id: 49878, description: "ACT 230V aansluitkabel C13 - C14 blauw. Lengte: 3 m",…},…]
filters: {price: ["0", "9999999999"], in_stock: "0", category: "", price_limit: [1, 8], search: "",…}
category: ""
favorite: {doc_count: 15, filtered: {doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: []}}
doc_count: 15
This is entirely based off of the API that you are communicating with. The api would have provide hooks to filter based on what you want. This could be done using query parameters `ie $.api("/catalog?type=favorites". But this is an impossible question to completely answer without that information.
Filter result.data and give only filtered items to watchlist when promise gets resolved.
function(result) {
$(".dashboardpage .widget-watchlist").render('pages/dashboard/widget-watchlist', {
watchlist: result.data.filter(item => favoriteItemIds.indexOf(item.id) != -1)
}).animo("enterContent");
}

Filter data by using nodejs

from one API I am getting these type of response. I need to get latitude, longitude of single entity. How can I filter this data by using javascript (node js).
header {
gtfs_realtime_version: "1.0"
incrementality: FULL_DATASET
timestamp: 1501132018
}
entity {
id: "1"
vehicle {
trip {
trip_id: "141.180717.42.1145"
schedule_relationship: SCHEDULED
route_id: "4T.C.141"
}
position {
latitude: -29.77179
longitude: 151.11717
bearing: 90.00001
}
timestamp: 1501131987
congestion_level: UNKNOWN_CONGESTION_LEVEL
stop_id: "23604"
vehicle {
id: "141"
label: "11:45am (141) Grafton City - Moree Town"
}
}
}
entity {
id: "2"
vehicle {
trip {
trip_id: "511.160717.90.1416"
schedule_relationship: SCHEDULED
route_id: "4T.C.511"
}
position {
latitude: -32.09544
longitude: 148.06787
bearing: 313.0
}
timestamp: 1501131974
congestion_level: UNKNOWN_CONGESTION_LEVEL
stop_id: "28211"
vehicle {
id: "511"
label: "02:16pm (511) Dubbo - Bourke"
}
}
}
All these data are of transportation API. If it would have been in JSON then we can get it by using foreach and by using its index.
Use javascript map function and extract only those fields which you want.

Add several nested JSON properties in a component in React

I am learning React and have a API request to OpenWeather that results in something like this:
{
coord: {
lon: -0.13,
lat: 51.51
},
weather: [{
id: 500,
main: "Rain",
description: "light rain",
icon: "10d"
}],
base: "stations",
main: {
temp: 293.21,
pressure: 1011,
humidity: 86,
temp_min: 292.45,
temp_max: 294.26
},
wind: {
speed: 1.54,
deg: 243,
gust: 3.08
},
rain: {
3h: 0.78
},
clouds: {
all: 56
},
dt: 1466431324,
sys: {
type: 3,
id: 10115,
message: 0.0463,
country: "GB",
sunrise: 1466394185,
sunset: 1466454093
},
id: 2643743,
name: "London",
cod: 200
}
I'm having problems using several parts of this JSON data.
I can call the result and first layer without problems, but calling any of the nested properties responds in an error saying it can't read the property of undefined.
I guess this is because the state is not defined, does it need to be defined for all the nested layers? I have defined the root, like this:
var React = require('react');
var Httprequest = require('../services/weatherservice.js');
var CurrentWeather = require('./CurrentWeather.jsx');
var WeatherApp = React.createClass({
getInitialState: function() {
return {currentWeather: '', apiCall: ''};
},
componentWillMount: function() {
Httprequest.get('London')
.then(function(data) {
this.setState({apiCall: data});
this.setState({currentWeather: data.weather[0]});
}.bind(this));
},
render: function() {
var Res = this.state.apiCall;
return (
<div>
<h1>Weather App</h1>
<CurrentWeather weatherNow={Res.main.humidity} />
</div>
);
}
});
module.exports = Weather;
Perhaps I shouldn't use state? I'm thinking of creating a solution where the user can change the city later on that's why I'm using state. I would appreciate it a lot if someone experienced could explain and perhaps refactor my example using a good practice so that I can learn doing it right.
Let me try to explain what you have done)
1) before first render you send request which will return data, at state you have {currentWeather: '', apiCall: ''}
2) request is async, so
.then(function(data) {
this.setState({apiCall: data});
this.setState({currentWeather: data.weather[0]});
}.bind(this))
this code will be called after several seconds
3) render method called, in which you doing something like this:
this.state.apiCall.main.humidity
but, for now in state you still have {currentWeather: '', apiCall: ''} so we will have error
how to solve this? simple just add some checks like
weatherNow={Res && Res.main && Res.main.humidity}
i also recommend you to read react styleguids, for now your component look ugly)

JSON to AS3 Object issue

I am new to JSON to AS3 Objects and am having issues trying to create an AS3 object that I can reference. Here is the JSON:
{
demo: {
Male: {
21-30: 2,
31-40: 0,
41-50: 0,
51-60: 0,
61-70: 0,
71-80: 0,
81+: 0
},
Female: {
21-30: 7,
31-40: 0,
41-50: 0,
51-60: 0,
61-70: 0,
71-80: 0,
81+: 0
}
},
days: 0
}
Here is the parsing code:
var JSONRequest: URLRequest = new URLRequest();
JSONRequest.method = URLRequestMethod.POST;
JSONRequest.url = "https://www.urlhere.com;
var loader: URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, handleResponse);
loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
loader.load(JSONRequest);
function handleResponse(event:Event):void{
var returnData:String = loader.data;
var parsedData:Object = JSON.parse(returnData);
}
I have tried and successfully looped through the object with for loops, but I don't want to have to do that, I want to be able to access the data as an object or array by accessing the properties in dot syntax. Object[0].property etc...
The really tricky part is that I don't know how large or how deep the data is nested. The one I added here is simple.
Here is more like what I will be getting:
{
products: {
Home & Garden: {
Kitchen: {
202: {
brand: "OXO",
description: "12 piece locktop container set",
descriptionLong: "Prepping, cooking and cleaning",
listPrice: "36.32",
sku: "925776",
upc: "719812032528"
},
238: {
brand: "Excalibur",
description: "Excalibur 2400 4-Tray Dehydrator",
descriptionLong: "Dehydration is the healthiest",
listPrice: "168.54",
sku: "947741",
upc: "029743240009"
},
352: {
brand: "Nostalgia",
description: "OldFashioned Kettle Corn Maker",
descriptionLong: "With the Nostalgia Electrics ",
listPrice: "35.49",
sku: "925843",
upc: "082677300218"
},
370: {
brand: "Joseph Joseph",
description: "Nest Plus Measuring (Set of 5 Cups - Multi Coloured)",
descriptionLong: "Nest™ Cups are a range of 5",
listPrice: "2.46",
sku: "926733",
upc: "5028420400342"
},
605: {
brand: "Nostalgia",
description: "Margarator-Frozen Drink Maker",
descriptionLong: "Mix up great-tasting margaritas",
listPrice: "140.68",
sku: "925851",
upc: "082677135889"
}
},
Housewares: {
206: {
brand: "Dyson",
description: "Dyson DC44 Animal",
descriptionLong: "DC44 Animal has a detachable",
listPrice: "406.51",
sku: "922846",
upc: "879957006362"
}
}
}
I will also add that I can request the formatting of the JSON I am receiving, so if there is a better way to format the data coming from the server, I am open to that.
Any help would be great.
I want to be able to access the data as an object or array by accessing the properties in dot syntax.
Use JSON.stringify and a replace callback before the parse call to rename the keys so you can access them via dot notation:
function newkey()
{
return "key" + Number(Math.random() * 1000).toFixed() + RegExp.$1
}
//Stringify JSON
var foo = JSON.stringify(parsedData);
/*
Replace numeric keys with a random number without replacing the delimiter
Replace spaces with underscores
*/
var bar = foo.replace(/\d+("?:)/g, newkey).replace(/\s/g,"_")
//Parse resulting string
var baz = JSON.parse(bar);
References
JSON - AS3 API Reference

Categories