This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 2 years ago.
I am attempting to create a weather app using the Openweather API. I am able to retrieve the JSON object successfully, but I am having trouble iterating through the object, I would like to access the weather details for specific dates and times but I just cannot for the life of me wrap my head around the concept. There were times where I was able to access the name of the JSON object, but when I attempt to access a specific weather detail from a specific date and time, I am met with errors constantly. Some of the information is so deeply nested that I am unsure exactly how to retrieve the information
fetch(`https://api.openweathermap.org/data/2.5/forecast?zip=${zip}&units=imperial&appid=5672e526c1cbc8d71aed230e5e151426`)
.then(response => response.json())
.then(json => {
console.log(json.list);
});
}, [apiSearch]);
If I simply try to add an index to the end of json.list:
console.log(json.list[1]);
I am sometimes met with errors such as Cannot convert undefined or null to object or something along those lines, I would like to know the best way to access the object array below and all of its information, thank you!
I've tried multiple approaches including Object.keys, mapping, etc. but I always get hit with an object is null error or something of the sorts. I would like to iterate through the 40 arrays and lets say access the temperature, every attempt to do so has led me to failure. Any help would be greatly appreciated, thank you!
Hope this will help you.
fetch(`https://api.openweathermap.org/data/2.5/forecast?zip=99501&units=imperial&appid=5672e526c1cbc8d71aed230e5e151426`)
.then(response => response.json())
.then(json => {
const forcasetList = json.list;
forcasetList.forEach(f => {
console.log(f.main.temp)
})
});
There can be several issues here:
Fetch and response status
Since you are using fetch the returned response may not always be a valid response, you should first check that you have an HTTP 200 status response e.g.:
fetch(url).then(
response => {
if (response.status !== 200) {
throw new Error(`Expected status 200 ok got status: ${response.status}`)
}
return response.json()
}
).then(...)
Impartial / Invalid data
I am not familiar with the openweathermap API but from what i can see in the API the forecast list should always have complete non null objects.
But you could add some validation or guards by either e.g.:
Using a JSON schema validation like AVJ
Or having a parse method that checks for the list and returns non null elements
fetch(url).then(
response => {
if (response.status !== 200) {
throw new Error(`Expected status 200 ok got status: ${response.status}`)
}
return response.json()
}
).then(
forecast => {
// here you could validate using something like AVJ to
// check that the json response is valid
if (!valid(forecast)) {
throw new Error('Invalid forecast data')
}
// Some custom filtering and validation example
const list = forecast.list || []
return list.filter(
item => {
// filter out null objects
if (!item) {
return false
}
// other validations.
...
// validate the date is within your range
if (item.dt ...) {
return false
}
// valid item
return true
}
)
.map (
// extract the weather part
item => item.weather
)
}
).then(
weatherItems => {
// work with weather items here
}
)
Related
I am creating a REST API and that will receive JSON data through POST. I'm creating the structure of the JSON now and was wondering what is considered best practice for how to send data signifying which Radio Button was selected on the sender's side. I thought of 3 possible ways to do it, but I'm open to other options if there's something better. Here are the 3 ways with UPS, FedEx and USPS being the sample options:
"UPS": false,
"FedEx": true,
"USPS": false
"ShippingCompany": 2 // 1 for UPS, 2 for FedEx, 3 for USPS
"ShippingCompany": "FedEx"
It depends on the use case and on who's consuming the API.
Your first solution is the least favorable of these three, since you want to implement a radio button. This would be more of a checkbox situation.
Variant 2 and 3 are interchangeable, but I'd use 3, since it's obvious what company you mean, instead of having to look up the meaning of the integers.
To go even further you could take a look at enums and their definition in openapi.
You can get it easily with querySelector:
let el = document.querySelector("input[name=radioName]:checked");
let val = el !== null ? el.value : "";
In your json you use like:
json = {
radioName: val
}
And then, to post, perhaps you may have to stringfy the json. Here is a sample code using the Fetch Api and recieves a json from the backend.
const getAllIncidents = () => {
var reqHeaders = new Headers();
var reqInit = { method: 'GET',
headers: reqHeaders,
mode: 'cors',
cache: 'default' ,
body: JSON.stringify( {
radioName: val
})
};
fetch(service_url, reqInit)
.then( r => {
return r.json();
}).then( json => {
console.log(json);
});
}
Obs 1.: querySelector returns null if the selector returns no element.
Obs 2.: remember using the same name for the radio button collection and diferent id for each one.
I'm using knex with MYSQL. I have a function that I called to show the data to the user, Also I'm using a view table which has 5 right join on it and I think it will take some time to return values from the table plus I added the WHERE condition on my knex and it looks like this :
var showClass = (teacherId , ClassId){
return new Promise((resolve , reject)=>{
knex.select().from('v_cardex_details').where({teacherId }).andWhere({id : ClassId}).then(classes =>{
resolve(classes)
}).catch(err=>{
console.error(`Show Teacher class Error: ${err}`)
reject (err)
})
})
}
and I call this general function to response some request something like this
exports.EditClass = (req,res)=>{
knex('Table').update({//Some update stuff here}).then(()=>{
showClass(req.user.id, req.params.id).then(data=>{
return res.status(200).json({data , message:''})
})
}).catch()
}
With the same input, this function after updating returns value and some times it returns an empty string, especially when it's on the hosting server most of the time it returns nothing but { message : '' }
Try to create simplified code by removing all the unnecessary wrappers and you might find where your problem is. AFAIK there is no way that that your {data , message:''} would create an object containing just {message: ''} without any additional attributes.
> var data = []
undefined
> {data, foo:1}
{ data: [], foo: 1 }
> data = undefined
undefined
> {data, foo:1}
{ data: undefined, foo: 1 }
> {data1, foo:1}
ReferenceError: data1 is not defined
The problem you are experiencing does not exist in from the code you have shared (though there are syntax errors and other problems).
EDIT:
res.json() uses JSON.stringify() to convert js object to JSON strings. So if value of data in your code is undefined instead of and array, that could explain the behavior you are experiencing:
λ node
> JSON.stringify({ test: undefined })
'{}'
As you can see JSON.stringify() omits the attributes with value undefined from the output JSON string.
So I'm working on a simple .html file .
I'm making the query:
var toDo= Trello.get('/lists/5d3ef8543a911e79f63df8c0/cards');
And I'm calling:
console.log(toDo);
And I'm getting this weird JSON
JSON returned by Trello API
So my problem is that I need to acces the responseJSON atributte, and I dont know ho to do it.
I already tried with toDo.responseJSON but it returns 'undefined'
How can I handle this type of JSON?
How can I access the atributes shown on the image?
Here is a basic example on how to handle the Promise:
Trello.get('/lists/5d3ef8543a911e79f63df8c0/cards')
.then(
(success) => {
console.log(success);
}
).catch(
(error) => {
console.log(error);
}
);
I am trying to fetch a simple JSON element from express.js. I am trying have React assign it to a state variable on the front end. I am using this code to do so:
componentDidMount() {
fetch("/user")
.then(response => response.json())
.then(result => this.setState({myUser:result}))
}
But when I run typeof myUser after this setState command, it says string instead of object. I've tried using JSON.parse(), etc. But either I get an error or it continues to assign the data as a string rather than JSON. What sort of syntax do I need to use in this fetch-then context to coerce the data assignment to be JSON?
I have read this link:
With this code:
componentDidMount(){
fetch('https://abx.com/data/tool.json').then(response =>{
if (!response.ok) throw Error('Response not ok')
return response.json(); // This is built in JSON.parse wrapped as a Promise
}).then(json => {
this.setState({"sections" : json});
}).catch(err =>{
console.log(err);
});
}
But it doesn't solve the problem. I ran this code directly in my application verbatim. When I run typeof on the variable, it says string instead of object. I looked at other posts on Stack Overflow, but I did not see a solution to this.
I figured out what was going wrong (after many hours of experimenting):
On the server side, I was creating a "homegrown" JSON object using string and variable concatenation. I also tried creating the JSON object by doing this:
var str = "name:" + name + ", department:" + department
var user = {str};
Both of these were not working in subtle ways... despite trying different types of gadgetry on the client side, I couldn't get React to interpret the data as a JSON object. But then I had an idea to construct the JSON on the server side (in Express.js) like this:
var user = {};
user["name"] = name;
user["department"] = department;
That immediately cleared things up on the server side and the client side. When using setState() in React, it now sets the value as an object (which was the goal all along).
I think this can be useful to others... if React doesn't seem to understand the JSON, perhaps it is being sent from the server in a subtly incorrect format.
I have been learning Angular and I made simple app which use database request and print all information from MySQL. In my service I made this method
getCharacters(){
return this.http.get('http://localhost/something/controller/characters')
.map(
(response: Response) => {
return response.json();
}
);
}
In characters-list component I used subscribe()
this.charactersService.getCharacters().subscribe(
(characters) => {
this.characters = characters;
}
);
It works of course but it's not practical. I want to use one array to a few components so I would retrieve data from MySQL one time and use this array in all components I want to.
How to do that?