Fetch JSON API nested data with Async function - javascript

complete noob here just trying to extract nested data from a JSON API.
Let's say that I want to retrieve and store in a variable the field received "amount" of the item number 3 (highlighted in the screenshot), what's the correct syntax? (The item number 3 is just an example, when finally found out how to fetch the data, my number 3 would become a variable and I will insert it in a loop because I want to extract also number 4,5,6 etc... If you are so kind, could you please give me help providing instead of a fixed number a variable that I can change within a loop?)
When the correct data is retrieved I want the received amount to be shown in the Span with ID="lat".
I am using the below syntax but it's not working at all:
<span id="lat"></span>
<script>
const api_url = 'https://MYAPIURL.com';
async function getAmount() {
const response = await fetch(api_url);
const data1 = await response.json();
const { data.history_list[3].receives[0].amount } } = data1;
document.getElementById('lat').textContent = data1;
}
getAddress();
</script>
Many appreciate your help, sers! Thank you :)

Try creating another variable to store the amount. Your syntax right now is assigning the value of the whole json object you received to the path of the received data object amount. This means you're nesting the received object back into the received object at the amount position.
You're also declaring a const here so JavaScript will likely think you're trying to 'destructure' the provided object except the syntax isn't exactly right for that so I imagine that might be causing problems too.
<script>
const api_url = 'https://MYAPIURL.com';
async function getAmount() {
const response = await fetch(api_url);
const data1 = await response.json();
const dataAmount= data1.history_list[3].receives[0].amount //changed line
document.getElementById('lat').textContent = dataAmount; //changed line to assign the textcontent to new variable
}
getAddress();
</script>

You can achieve it by this simple way dynamically.
Working Demo :
const data = {
history_list: [{
receives: [{
amount: 10
}]
}, {
receives: [{
amount: 20
}]
}, {
receives: [{
amount: 30
}]
}, {
receives: [{
amount: 40
}]
}]
};
let amount = 0;
data.history_list.forEach((obj) => {
obj.receives.forEach((amountObj) => {
amount += amountObj.amount;
});
});
document.getElementById('lat').innerHTML = `Total Amount: ${amount}`
<div id="lat"></div>

Related

How to parse json if Key'name dynamicly changes each time node js

I receive JSON data from the service, but the keys change in the data with each request, below I will give an example in three versions.
Exmaple 1:
{
"trackingPayloads": {
"Rltyn4gLRIWRKj9kS0YpWXytG81GZwcPWjEE7f31ALlq": "{"title":"Red Shoes","index":3,"id":"17777","type":"category"}',
"ywtA6OyM0hzVZZvnUjxoxJDI1Er9ArfNr8XKyi1D5Zzk": "{"title":"White Shoes","index":3,"id":"17777","type":"category"}',
}
}
Example 2:
{
"trackingPayloads": {
"36tW7DqZ3H9KKBEAumZmowmUwmDRmVCjQgv5zi9GM3Kz": "{"title":"Red Shoes","index":3,"id":"17777","type":"category"}',
"OgtE51n3YtvrVXWLFjPmpnRt2k5DExF7ovxmBTZrZ6wV": "{"title":"White Shoes","index":3,"id":"17777","type":"category"}',
}
}
Example 3:
{
"trackingPayloads": {
"k2toY29glt2JEp9Wi1X5M7ocno0E0mS4JQVyDuGyQ2rM": "{"title":"Red Shoes","index":3,"id":"17777","type":"category"}'",
"5ef2ec3c3573eebecc9690b69619ec7b9c93b609": "{"title":"White Shoes","index":3,"id":"17777","type":"category"}',
}
}
As you can see, the data included in the keys does not change since I am requesting the same information, but the key will change with each request.
Please help, what are the options to get the data Title, Index and any other content in these keys using node js?
Only one option came to my mind - to rename the keys upon receipt in 1,2,3 ... and then get data from them, but this needs to be done dynamically, since about 120 requests per minute are made, you need to get this data quickly, there are no options to save it to a file (I didn’t understand how)
UPDATE, added my code.
I am attaching an example of my code, the idea is to eventually get the data I need from the right keys from trackingPayloads, please help with the code <3
const AwaitAPIResponse = await ProductAPI(product_sku);
const $ = cheerio.load(AwaitAPIResponse);
const JSONDATA = [];
$('pre').each(function() {
JSONDATA.push($(this).text());
});
const ProductJson = JSON.parse(JSONDATA[0]) // this is where I get all the data
const MainJson = ProductJson["trackingPayloads"] // here I go to the trackingPayloads you saw above
How can I get the data I need?
You can use Object.keys() to get all the different keys of an object and use a loop to go through them.
Therefore, you can rework this code in such a way that each of the values is stored as an element in an array, maybe makes the data easier to work with:
const convert = object => {
const ret = []
for (const key of Object.keys(object)) {
ret.push(object[key])
}
return ret
}
This will give you following result for your use case:
[{"title":"Red Shoes","index":3,"id":"17777","type":"category"},
{"title":"Red Shoes","index":3,"id":"17777","type":"category"}]
The way you'd call this is as follows:
const some_parsed_json = {
"k2toY29glt2JEp9Wi1X5M7ocno0E0mS4JQVyDuGyQ2rM": {
title:"Red Shoes",
index:3,
id:"17777",
type:"category"
},
"5ef2ec3c3573eebecc9690b69619ec7b9c93b609": {
title:"Red Shoes",
index:3,
id:"17777",
type:"category"
}
}
const json_object_values = convertor(some_parsed_json)
If you don't car about the key you could use Object.values on the received object to get the values
Object.values(payload)
// With your example it will return:
// [{"title":"Red Shoes","index":3,"id":"17777","type":"category"},
// {"title":"Red Shoes","index":3,"id":"17777","type":"category"}]
or in a more complete example
async function getParsedValues() {
const responseString = await service.getData(); // '{"trackingPayloads":{"Rltyn4gLRIWRKj9kS0YpWXytG81GZwcPWjEE7f31ALlq":{"title":"Red Shoes","index":3,"id":"17777","type":"category"},"ywtA6OyM0hzVZZvnUjxoxJDI1Er9ArfNr8XKyi1D5Zzk":{"title":"White Shoes","index":3,"id":"17777","type":"category"}}}'
const parsedResponse = JSON.parse(responseString); // { trackingPayloads: { Rltyn4gLRIWRKj9kS0YpWXytG81GZwcPWjEE7f31ALlq: { title:'RedShoes', index: 3, id: '17777', type: 'category' }, ywtA6OyM0hzVZZvnUjxoxJDI1Er9ArfNr8XKyi1D5Zzk:{title:'WhiteShoes', index: 3, id: '17777', type: 'category' } }}
const values = Object.values(parsedResponse); // [{"title":"Red Shoes","index":3,"id":"17777","type":"category"}, {title:'WhiteShoes', index: 3, id: '17777', type: 'category' }]
return values;
}

Get json data from from django-rest-api with react frontend into a variable

I am new to react and javascript. I am trying to get some data INTO A VARIABLE in react from django-rest API.
I am using this variable in another function using react-beautiful-dnd.
I have the API set up and CORS also set up.
This is the output in http://127.0.0.1:8000/api/column_names/
I am trying to get this as a json object in react frontend.
const getData = async () => {
let response = await fetch("http://127.0.0.1:8000/api/column_names/");
let data = await response.json();
console.log(data); // line 29
return data;
};
let columnFromBackend = getData();
console.log(columnFromBackend); // line 34
This is the output
Is there any way to get this data into the variable columnFromBackend
I am trying to get the equivalent of this value.
let columnFromBackend = {
idone: {
name: "In progress",
items: [{ id: "hjnmkjnh", content: "first" }],
},
idtwo: {
name: "Todod",
items: [],
},
};
If I declare the variable directly like this, then this is the output that I am getting and what I am trying to get from the api.
You need to change your second to last line to
let columnFromBackend = await getData();
Which version of node are you using?
Go to node_modules/react-scripts/config and open webpack.config.js file
then look for module.exports and add
experiments:{ topLevelAwait: true }
Then change let columnFromBackend = getData(); to let columnFromBackend = await getData();

mongoosejs - find() using nested objects

question is possibly a duplicate but I haven't found anything that provides an appropriate answer to my issue.
I have an ExpressJS server which is used to provide API requests to retrieve data from a MongoDB database. I am using mongoosejs for the MongoDB connection to query/save data.
I am building a route that will allow me to find all data that matches some user input but I am having trouble when doing the query. I have spent a long while looking online for someone with a similar issue but coming up blank.
I will leave example of the code I have at the minute below.
code for route
// -- return matched data (GET)
router.get('/match', async (req, res) => {
const style_data = req.query.style; // grab url param for style scores ** this comes in as a string **
const character_data = req.query.character; // grab url param for character scores ** this comes in as a string **
// run matcher systems
const style_matches = style_match(style_data);
res.send({
response: 200,
data: style_matches
}); // return data
});
code for the query
// ---(Build the finder)
const fetch_matches_using = async function(body, richness, smoke, sweetness) {
return await WhiskyModel.find({
'attributes.body': body,
'attributes.richness': richness,
'attributes.smoke': smoke,
'attributes.sweetness': sweetness
});
}
// ---(Start match function)---
const style_match = async function (scores_as_string) {
// ---(extract data)---
const body = scores_as_string[0];
const richness = scores_as_string[1];
const smoke = scores_as_string[2];
const sweetness = scores_as_string[3];
const matched = [];
// ---(initialise variables)---
let match_count = matched.length;
let first_run; // -> exact matches
let second_run; // -> +- 1
let third_run; // -> +- 2
let fourth_run; // -> +- 3
// ---(begin db find loop)---
first_run = fetch_matches_using(body, richness, smoke, sweetness).then((result) => {return result});
matched.push(first_run);
// ---(return final data)---
return matched
}
example of db object
{
_id: mongoid,
meta-data: {
pagemd:{some data},
name: whiskyname
age: whiskyage,
price: price
},
attributes: {
body: "3",
richness: "3",
smoke: "0",
sweetness: "3",
some other data ...
}
}
When I hit the route in postman the JSON data looks like:
{
response: 200,
data: {}
}
and when I console.log() out matched from within the style match function after I have pushed the it prints [ Promise(pending) ] which I don't understand.
if I console.log() the result from within the .then() I get an empty array.
I have tried using the populate() method after running the find which does technically work, but instead of only returning data that matches it returns every entry in the collection so I think I am doing something wrong there, but I also don't see why I would need to use the .populate() function to access the nested object.
Am I doing something totally wrong here?
I should also mention that the route and the matching functions are in different files just to try and keep things simple.
Thanks for any answers.
just posting an answer as I seem to have fixed this.
Issue was with my .find() function, needed to pass in the items to search by and then also a call back within the function to return error/data. I'll leave the changed code below.
new function
const fetch_matches_using = async function(body, richness, smoke, sweetness) {
const data = await WhiskyModel.find({
'attributes.body': body,
'attributes.richness': richness,
'attributes.smoke': smoke,
'attributes.sweetness': sweetness
}, (error, data) => { // new ¬
if (error) {
return error;
}
if (data) {
console.log(data)
return data
}
});
return data; //new
}
There is still an issue with sending the found results back to the route but this is a different issue I believe. If its connected I'll edit this answer with the fix for that.

Is there a way to insert data from api calls into an object before its imported? Code is running before I'm able to create a variable with data

I'm trying to create variables and filling them with data from json api calls, but the code runs before the api calls can be made, resulting in the variables showing up empty when I try to use them. I can't figure out how to finish filling my object with data from api calls before it's being imported on a different page.
I understand that my issue is that most of the code runs before I'm able to finish setting variables that get their data from an api call, I can't figure out how to fill barChartData with variables from api calls. Any help would be insanely appreciated
//Calls json api
async function fetchJSONAsync(url) {
let response = await fetch(url);
let body = await response.json();
return body;
}
//Creating movie1 variable
let movie1 = fetchJSONAsync('https://facebook.github.io/react-native/movies.json').then((apiData) => {
movie1 = apiData.movies[0].title;
console.log(movie1); //Logs the correct data since it waits before running
});
console.log(movie1); //Doesnt log the correct data cause code runs before movie1 is done redefining itself
//Bar Chart Data -> I want to insert data from the api calls into this (simple Bar Chart from https://www.npmjs.com/package/react-native-chart-kit)
console.log(movie1) results in "{ _40: 0, _65: 0, _55: null, _72: null }", I'm assuming because the api call is never finished before it's being tossed into barChartData, which gives me the Invariant Violation: Objects are not valid as a React Child error.
const barChartData = {
labels: [movie1', 'Movie Title 2', 'Movie Title 3'], //<<<Insert movie1 variable in here
datasets: [{
data:
[
200, //Irrelevant
250, //Irrelevant
255 //Irrelevant
]
}]
}
Thanks again in advance for any help given.
You can also do like this :
yourMethodName = async () => {
const movie1 = await fetchJSONAsync('https://facebook.github.io/react-native/movies.json');
console.log(movie1.movies[0].title);
}
I think, and i'm no expert, but if you can add an await to the fetchJSONAsync call and a return within the then clause you should be able to achieve what you need.
let movie1 = await fetchJSONAsync('https://facebook.github.io/react-native/movies.json').then((apiData) => {
movie1 = apiData.movies[0].title;
console.log(movie1); //Logs the correct data since it waits before running
return movie1;
})
Pass movie1 data from state.Take another variable isFetched inital value false.
Update isFetched true once api return data.
On barChartData side, if isFetched false then show loader else render data.

React Native - How to save map using AsyncStorage

I try to save user inputs as a JS map using AsyncStorage in my React Native app.
It shows no errors when saving, but I got "[object Map]" when I tried to get the data back.
There is the simplified version of my user map. the actual User object has way more properties than this, but the ID is always same as the map key.
const dataKey = 'user-data';
let data = new Map();
data.set(1, { name: 'John', id: 1, title: 'Mr.' })
data.set(2, { name: 'Johanna', id: 2, title: 'Miss.' })
There is the code for saving the data.
async saveDate = (dataKey, data) => {
try {
await AsyncStorage.setItem(dataKey, data.toString());
} catch (err) {
console.log(err);
}
}
There will be more than 200 users in this map.
Any idea how to save complex data structure in react native?
Instead of converting your data to a string you need to save it as JSON. Change
await AsyncStorage.setItem(dataKey, data.toString());
to
await AsyncStorage.setItem(dataKey, JSON.stringify(data));
See this link to the official documents for more details: https://facebook.github.io/react-native/docs/asyncstorage.html#mergeitem
Like one of the other answers states, you need to save the data as JSON.
However, with you won't be able to simply convert data to JSON. Instead you will need to spread the array entries of Map and pass that to JSON.stringify().
So change
await AsyncStorage.setItem(dataKey, data.toString());
to
await AsyncStorage.setItem(dataKey, JSON.stringify([...data]));
And then when you want to get the item from Async you will need to convert it back to Map, i.e.
const jsonData = AsyncStorage.getItem(dataKey)
const mapData = new Map(jsonData)
The provided answers will not quite work. You can't create the new Map after reading back json without parsing first. This works:
saveData = async () => {
const dataKey = 'user-data';
let data = new Map();
data.set(1, { name: 'John', id: 1, title: 'Mr.' })
data.set(2, { name: 'Johanna', id: 2, title: 'Miss.' })
try {
await AsyncStorage.setItem(dataKey, JSON.stringify([...data]));
} catch (err) {
console.log(err);
}
const jsonData = await AsyncStorage.getItem(dataKey)
const parseData = JSON.parse(jsonData)
const mapData = new Map(parseData)
console.log(mapData);
//get a list of IDs
console.log(Array.from(mapData.keys()));
}
For 200 values this is a lot of overhead. I would consider using sprintf/sscanf libraries and just store a string, for instance one row of data per line.
This will only work if every row in the table has the same amount of elements and you don't change the layout. Of course it would all be on you to convert the string back to objects so you can recreate the Map. Just a thought!

Categories

Resources