How to get JSON from URL in JavaScript? - javascript

This URL returns JSON:
{
query: {
count: 1,
created: "2015-12-09T17:12:09Z",
lang: "en-US",
diagnostics: {},
...
}
}
I tried this, and it didn't work:
responseObj = readJsonFromUrl('http://query.yahooapis.com/v1/publ...');
var count = responseObj.query.count;
console.log(count) // should be 1
How can I get a JavaScript object from this URL's JSON response?

You can use jQuery .getJSON() function:
$.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20%2a%20from%20yahoo.finance.quotes%20WHERE%20symbol%3D%27WRC%27&format=json&diagnostics=true&env=store://datatables.org/alltableswithkeys&callback', function(data) {
// JSON result in `data` variable
});
If you don't want to use jQuery you should look at this answer for pure JS solution.

If you want to do it in plain javascript, you can define a function like this:
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status === 200) {
callback(null, xhr.response);
} else {
callback(status, xhr.response);
}
};
xhr.send();
};
And use it like this:
getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20%2a%20from%20yahoo.finance.quotes%20WHERE%20symbol%3D%27WRC%27&format=json&diagnostics=true&env=store://datatables.org/alltableswithkeys&callback',
function(err, data) {
if (err !== null) {
alert('Something went wrong: ' + err);
} else {
alert('Your query count: ' + data.query.count);
}
});
Note that data is an object, so you can access its attributes without having to parse it.

With Chrome, Firefox, Safari, Edge, and Webview you can natively use the fetch API which makes this a lot easier, and much more terse.
If you need support for IE or older browsers, you can also use the fetch polyfill.
let url = 'https://example.com';
fetch(url)
.then(res => res.json())
.then(out =>
console.log('Checkout this JSON! ', out))
.catch(err => { throw err });
MDN: Fetch API
Even though Node.js does not have this method built-in, you can use node-fetch which allows for the exact same implementation.

ES8(2017) try
obj = await (await fetch(url)).json();
async function load() {
let url = 'https://my-json-server.typicode.com/typicode/demo/db';
let obj = await (await fetch(url)).json();
console.log(obj);
}
load();
you can handle errors by try-catch
async function load() {
let url = 'http://query.yahooapis.com/v1/publ...';
let obj = null;
try {
obj = await (await fetch(url)).json();
} catch(e) {
console.log('error');
}
console.log(obj);
}
load();

Axios is a promise based HTTP client for the browser and node.js.
It offers automatic transforms for JSON data and it's the official recommendation from the Vue.js team when migrating from the 1.0 version which included a REST client by default.
Performing a GET request
// Make a request for a user with a given ID
axios.get('http://query.yahooapis.com/v1/publ...')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Or even just axios(url) is enough as a GET request is the default.

Define a function like:
fetchRestaurants(callback) {
fetch(`http://www.restaurants.com`)
.then(response => response.json())
.then(json => callback(null, json.restaurants))
.catch(error => callback(error, null))
}
Then use it like this:
fetchRestaurants((error, restaurants) => {
if (error)
console.log(error)
else
console.log(restaurants[0])
});

async function fetchDataAsync(url) {
const response = await fetch(url);
console.log(await response.json());
}
fetchDataAsync('paste URL');

//Resolved
const fetchPromise1 = fetch(url);
fetchPromise1.then(response => {
console.log(response);
});
//Pending
const fetchPromise = fetch(url);
console.log(fetchPromise);

this morning, i also had the same doubt and now its cleared
i had just used JSON with 'open-weather-map'(https://openweathermap.org/) api and got data from the URL in the index.html file,
the code looks like this:-
//got location
var x = document.getElementById("demo");
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(weatherdata);
} else {
x.innerHTML = "Geolocation is not supported by this browser.";
}
//fetch openweather map url with api key
function weatherdata(position) {
//put corrdinates to get weather data of that location
fetch('https://api.openweathermap.org/data/2.5/weather?lat='+position.coords.latitude+'&lon='+position.coords.longitude+'&appid=b2c336bb5abf01acc0bbb8947211fbc6')
.then(response => response.json())
.then(data => {
console.log(data);
document.getElementById("demo").innerHTML =
'<br>wind speed:-'+data.wind.speed +
'<br>humidity :-'+data.main.humidity +
'<br>temprature :-'+data.main.temp
});
}
<div id="demo"></div>
i had give api key openly because i had free subscription, just have a free subscriptions in beginning.
you can find some good free api's and keys at "rapidapi.com"

as #DanAlboteanu answer in this page and some error corection of that javascript my suggested code is:
fetchRestaurants((error, data) => {
if (error)
console.log(error);
else
console.log(data)
});
and fetchRestaurants method is(please replace your json url with {your url of json data}):
function fetchRestaurants(callback) {
fetch("{your url of json data}")
.then(response => response.json())
.then(json => callback(null, json))
.catch(error => callback(error, null))
}

You can access JSON data by using fetch() in JavaScript
Update url parameter of fetch() with your url.
fetch(url)
.then(function(response){
return response.json();
})
.then(function(data){
console.log(data);
})
Hope It helps, it worked perfectly for me.

Related

How to get response from a dynamic amount of URL's and combine JSON response from all of them

Currently I have a small JSON file with a list of URL's to fetch data from, this amount can change at any time, so I have built a small function to request from the URL's and log a JSON response from each of them, but currently I need to combine the responses from all of them and send them in a res.json format.
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
databases.find({}, function(err, docs) {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
axios.post(url, req.body)
.then(function(response) {
var o1 = response.data
var obj = Object.assign(o1);
console.log(obj)
//res.json(obj.data);
})
.catch(function(error) {
console.log(error)
res.json({ success: false });
});
}
});
} catch {
console.log(error)
res.json({ success: false });
}
});
I was thinking that the code would look something like this (Pseudo code)
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
dynamic(var)object
databases.find({}, function(err, docs) {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
axios.post(url, req.body)
.then(function(response) {
add(response) to (var) object
})
.catch(function(error) {
console.log(error)
res.json({ success: false });
});
}
when function is finished (console.log[(var)]) with added JSON from all of the requests
});
} catch {
console.log(error)
res.json({ success: false });
}
});
I have seen solutions where the existing JSON data is overwritten if both the Response and JSON Object have the same value, and I want to avoid that.
I have tried storing the response data inside a var, but it would get overwritten if the data inside the var and the response had the same value.
I have also tried adding them together separately, but that makes numerous arrays, and I don't want that.
How you combine the json responses received completely depends on the information content of the response json. You can combine the responses as shown below or write custom logic to combine the jsons depending on actual responses and send the result.
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
const JsonAggreagate = []
databases.find({}, async function(err, docs) {
try {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
let result = await axios.post(url, req.body)
//LOGIC FOR COMBINING JSON RESPONSES
JsonAggreagate.push({url: url, result : result})
}
} catch (error) {
console.log(error)
res.json({ success: false });
}
//when function is finished (console.log[(var)]) with added JSON from all of the requests
res.json({ success: true, result : JsonAggreagate});
});
} catch {
console.log(error)
res.json({ success: false });
}
});

Save responses to multiple GET requests in a single local json file - node.js

The problem:
I have a function that maps over countries and regions and creates an array of urls, then makes a GET request to each one. I want to save the responses in a single json file, and I want this function to handle that as well.
Expected results:
I expected to be able to run the function as needed (like when source data is updated), and get a new or updated local json file with all the data objects in one array.
Actual results:
A file with only one record, an array with the last response object.
What I've tried:
I tried using fs.writeFile and fs.readFile. I did not get any errors, but the resulting file had only one record, even though console showed all the requests being made. It seemed that each response was being written over the previous.
Minimum reproducable (node.js) example:
const fs = require('fs')
// subset of countries and codes for demo purposes
const countryDirList = [
'antarctica',
'central-asia',
]
const fbCountryCodes = [
{ "region": "antarctica", "codes": ["ay", "bv"] },
{ "region": "central-asia", "codes": ["kg", "kz"] },
]
const callingUrlsInSequence = async () => {
fs.writeFile('./test.json', '[]', function (err) {
if (err) throw err
console.log('File - test.json - was created successfully.')
})
try {
const urlConstructor = countryDirList.map(async (country) => {
console.log('countries mapped', country)
return fbCountryCodes.filter(async (f) => {
if (country === f.region) {
const urls = f.codes.map(async (c) => {
const response = await axios({
method: 'get',
url: `https://raw.githubusercontent.com/factbook/factbook.json/master/${country}/${c}.json`,
responseType: 'json',
headers: {
'Content-Type': 'application/json',
},
})
fs.readFile('./test.json', function (err, data) {
let json = JSON.parse(data)
json.push(response.data)
setTimeout(() => {
fs.writeFile('./test.json', JSON.stringify(json), function (err) {
if (err) throw err
console.log('The "data to append" was appended to file!')
})
}, 1000)
})
return response.data
})
const dataArr = await Promise.all(urls)
dataArr.map((item) =>
console.log(
'dataArr',
item.Government['Country name']['conventional short form']
)
)
}
})
})
} catch (err) {
console.log('axios error: ', err)
}
}
callingUrlsInSequence()
I'm re-writing this question now because it kept getting downvoted, and I could see that it was not very concise.
I can also see now, that obviously, the fs.readFile inside the fs.writeFile is not going to work in the code I provided, but I'm leaving it there in case it might help someone else, combined with the solution I provided in response to my own question.
I ended up learning how to solve this problem with both node-fetch and axios. They are not exactly the same.
For both:
First, check for existence of destination file, and create one if it's not already there.
const createNew = () => {
try {
if (existsSync('./data.json')) {
console.log('file exists')
return
} else {
writeFile('./data.json', '[]', (error, data) => {
if (error) {
console.log('fs.writeFile - create new - error: ', error)
return
}
})
}
} catch (err) {
console.log('fs.existsSync error: ', err)
}
}
createNew()
Then make the array of urls:
const countryDirList = [...countries]
const fbCountryCodes = [...codes]
const urls = []
// maybe a reducer function would be better, but my map + filter game is much stronger X-D
const makeUrls = (countriesArr, codesArr) =>
countriesArr.map((country) => {
return codesArr.filter((f) => {
if (country === f.region) {
return f.codes.map((code) => {
return urls.push(
`https://raw.githubusercontent.com/factbook/factbook.json/master/${country}/${code}.json`
)
})
}
})
})
makeUrls(countryDirList, fbCountryCodes)
Next, make the requests.
Axios:
fs.readFile('./data.json', (error, data) => {
if (error) {
console.log(error)
return
}
Promise.all(
urls.map(async (url) => {
let response
try {
response = await axios.get(url)
} catch (err) {
console.log('axios error: ', err)
return err
}
return response
})
)
.then((res) => {
const responses = res.map((r) => r.data)
fs.writeFile('./data.json', JSON.stringify(responses, null, 2), (err) => {
if (err) {
console.log('Failed to write data')
return
}
console.log('Updated data file successfully')
})
})
.catch((err) => {
console.log('axios error: ', err)
})
})
Node-fetch:
//same basic structure, readFile with fetch and write file inside
fs.readFile('./data2.json', (error, data) => {
if (error) {
console.log(error)
return
}
async function fetchAll() {
const results = await Promise.all(
urls.map((url) => fetch(url).then((r) => r.json()))
)
fs.writeFile('./data2.json', JSON.stringify(results, null, 2), (err) => {
if (err) {
console.log('Failed to write data')
return
}
console.log('Updated data file successfully')
})
}
fetchAll()
})
Both methods produce exactly the same output: a json file containing a single array with however many response objects in it.

Decode a Uint8Array into a JSON

I am fetching data from an API in order to show sales and finance reports, but I receive a type gzip file which I managed to convert into a Uint8Array. I'd like to somehow parse-decode this into a JSON file that I can use to access data and create charts in my frontend with.
I was trying with different libraries (pako and cborg seemed to be the ones with the closest use cases), but I ultimately get an error Error: CBOR decode error: unexpected character at position 0
This is the code as I have it so far:
let req = https.request(options, function (res) {
console.log("Header: " + JSON.stringify(res.headers));
res.setEncoding("utf8");
res.on("data", function (body) {
const deflatedBody = pako.deflate(body);
console.log("DEFLATED DATA -----> ", typeof deflatedBody, deflatedBody);
console.log(decode(deflatedBody));
});
res.on("error", function (error) {
console.log("connection could not be made " + error.message);
});
});
req.end();
};
I hope anyone has stumbled upon this already and has some idea.
Thanks a lot!
Please visit this answer https://stackoverflow.com/a/12776856/16315663 to retrieve GZIP data from the response.
Assuming, You have already retrieved full data as UInt8Array.
You just need the UInt8Array as String
const jsonString = Buffer.from(dataAsU8Array).toString('utf8')
const parsedData = JSON.parse(jsonString)
console.log(parsedData)
Edit
Here is what worked for me
const {request} = require("https")
const zlib = require("zlib")
const parseGzip = (gzipBuffer) => new Promise((resolve, reject) =>{
zlib.gunzip(gzipBuffer, (err, buffer) => {
if (err) {
reject(err)
return
}
resolve(buffer)
})
})
const fetchJson = (url) => new Promise((resolve, reject) => {
const r = request(url)
r.on("response", (response) => {
if (response.statusCode !== 200) {
reject(new Error(`${response.statusCode} ${response.statusMessage}`))
return
}
const responseBufferChunks = []
response.on("data", (data) => {
console.log(data.length);
responseBufferChunks.push(data)
})
response.on("end", async () => {
const responseBuffer = Buffer.concat(responseBufferChunks)
const unzippedBuffer = await parseGzip(responseBuffer)
resolve(JSON.parse(unzippedBuffer.toString()))
})
})
r.end()
})
fetchJson("https://wiki.mozilla.org/images/f/ff/Example.json.gz")
.then((result) => {
console.log(result)
})
.catch((e) => {
console.log(e)
})
Thank you, I actually just tried this approach and I get the following error:
SyntaxError: JSON Parse error: Unexpected identifier "x"
But I managed to print the data in text format using the below function:
getFinancialReports = (options, callback) => {
// buffer to store the streamed decompression
var buffer = [];
https
.get(options, function (res) {
// pipe the response into the gunzip to decompress
var gunzip = zlib.createGunzip();
res.pipe(gunzip);
gunzip
.on("data", function (data) {
// decompression chunk ready, add it to the buffer
buffer.push(data.toString());
})
.on("end", function () {
// response and decompression complete, join the buffer and return
callback(null, buffer.join(""));
})
.on("error", function (e) {
callback(e);
});
})
.on("error", function (e) {
callback(e);
});
};
Now I would need to pass this into a JSON object.

Using fetch from JavaScript to get one meal recipe form an API "TheMealDB" I can´t access=>erro 404

/* Create an event loader to all of the events */
document.addEventListener("DOMContentLoaded", () =>{
let button = document.querySelector("#button");
let firstCont = document.querySelector(".container2");
let secondCont = document.querySelector(".container3");
button.addEventListener("click", () => {
dataRenovation(firstCont, secondCont);
firstCont.classList.remove("hidden");
secondCont.classList.remove("hidden");
})
});
function dataRenovation(first, second){
const option = {
method: "GET",
headers: {
"Content-type": "application/json",
"Access-Control-Allow-Origin": "https://www.themealdb.com/"
}
};
fetch("www.themealdb.com/api/json/v1/1/random.php", option)
.then(response => {
alert(response.url);
if(response.ok) {
return response.json;
}else {
throw new Error(response.status);
}
})
.then(data => {
alert("Data: " + data);
})
.catch(err => {
alert("Error: " + err.message);
});
}
It return error: 404. I have noticed that the url returned is not the original, Js return the normal url preceded by my actual domain direction at this case http://127.0.0.1:5500/ as the normal domain.
I readed something about corss and added "Access-Control-Allow-Origin": "https://www.themealdb.com/" to can access to the normal API but I don´t know if that´s the correct inplementation.
I´d like to get some help and if you can let me some links to learn more about API and Corss.
Thank you.

Trying to load JSON via url in react-native but not getting correct response

getData() {
return fetch("http://bitcfeedcms.rf.gd/script.php")
.then(response => {
console.log(response);
response.json();
})
.then(responseJson => {
this.setState({ data: responseJson });
})
.catch(error => {
console.error(error);
});
}
I also tried by putting ?l=1 like " bitcfeedcms.rf.gd/script.php?l=1 ".
The main json file is " bitcfeedcms.rf.gd/feed_data.json ". So i tried "http://bitcfeedcms.rf.gd/feed_data.json?l=1" this too but nothing changed
What i have to do now to get the json data and use it in my app...Please help
You are using the arrow function wrong. Instead of this:
fetch("http://bitcfeedcms.rf.gd/script.php")
.then(response => {
console.log(response);
response.json();
})
.then(responseJson => {
this.setState({ data: responseJson });
})
You should return the response.json()
fetch("http://bitcfeedcms.rf.gd/script.php")
.then(response => {
console.log(response);
return response.json();
})
.then(responseJson => {
this.setState({ data: responseJson });
})
This way you can reach responseJson in the next then.
Also, if your app complains about fetch() network request failed probably it's about Info.plist or Manifest configuration error. See this topic.
For iOS, you can try the same request with this https dummy json url:
https://jsonplaceholder.typicode.com/posts/1
http://bitcfeedcms.rf.gd/script.php , this link returns multiple sets of JSON.
([{"FeedTitle":"Debotos","FeedDescription":"First Feed Testing....."},{"FeedTitle":"Akash","FeedDescription":"Creating a clan named \"Khulna Sparkers\""},{"FeedTitle":"Ripon","FeedDescription":"My brother and my one of the closest individual"}])
try this . . .
getData() {
fetch("http://bitcfeedcms.rf.gd/script.php")
.then(response => {
console.log(response);
response.json();
})
.then(responseJson => {
var length = responseJson.length;
for (var a = 0; a<length;a++) {
var FeedTitle = responseJson[a].FeedTitle; //<-variable from your response json
var FeedDescription = responseJson[a].FeedDescription; //<-from your response json
console.log(FeedTitle);
console.log(FeedDescription);
}
})
.catch(error => {
console.error(error);
});
}
try axios
npm install --save axios
state = {data:[]};
componentWillMount() {
axios.get('http://bitcfeedcms.rf.gd/script.php')
.then(response =>this.setState({data:response.data}));
}

Categories

Resources