Reputation: 53
I am trying to fetch a JSON file from a api website using the below code but i am getting an error saying "Unexpected end of JSON input" when I fetch using the below code
var express = require("express");
var app = express();
var body = require("body-parser");
var https = require("https");
app.get("/results", function (req, res) {
https.get("https://www.omdbapi.com/?apikey=d49698c3&s=harry", function (response) {
response.on("data", function (data) {
var got = JSON.parse(data);
res.send(got.Title);
})
})
});
Upvotes: 5
Views: 47899
Reputation: 1925
There are a couple of wrong assumptions in your code.
1 - Looking at the data, you can see that the property Title is in every single object inside the Search property, which is an Array
, thus when the JSON gets correctly parsed, you'll have an issue with got.Title
2 - The event data of the object response can be called multiple times until you can get all the data, every time it gets called, you receive a chunk of the data.
Once all the data has been sent the end event is called and there is the place to parse the JSON.
Your code is trying to parse an incomplete JSON string, just the first chunk.
The most common approach is to declare an array outside the functions that will handle the events data and end. For every data event you push the chunk into the outside array and on the end event you concatenate it.
Check this out:
var express = require('express')
var app = express()
var body = require('body-parser')
var https = require('https')
app.get('/results', function (req, res) {
https.get('https://www.omdbapi.com/?apikey=d49698c3&s=harry', function (response) {
const chunks = []
response.on('data', function (chunk) {
chunks.push(chunk)
})
response.on('end', function () {
const data = Buffer.concat(chunks)
var got = JSON.parse(data)
// Try this one out as well
// res.json(got)
res.send(got.Search[0].Title)
})
})
})
app.listen(3000)
I just tested the code above and it works like a charm.
Upvotes: 11
Reputation: 9
For everyone who's having the same issue. I found a solution:
As what @Maestre San - has explained, you're parsing an incomplete JSON data. That's why you're getting the error. I've tried both solutions suggested by both but it still wasn't working for me. Hence, I researched and found out that first of all, you will need to store the data in an empty variable, once the data stream is done, you can then parse it by doing the following:
response.on("end", function () {
var jsonParse = JSON.parse(newsItems);
});
The full code is:
app.get("/", function (req, res) {
const queryString = "mamamoo";
const url = "https://newsapi.org/v2/everything?apiKey=<API_KEY>&qInTitle=" + queryString;
https.get(url, function (response) {
var newsItems = '';
response.on("data", function (data) {
newsItems += data;
});
response.on("end", function () {
var jsonParse = JSON.parse(newsItems);
console.log(jsonParse);
});
});
});
So as to explain what I did:
First, I make sure to catch any request made to my server. I then used the native node https request to make a request to the api, catching the response (the response contains statusCode and other response body).
However, I want to access the data body, so I performed "response.on". First, I captured the data in chunks and stored it in an empty variable.
Why store it in an empty variable? Because if I didn't and continued to parse it, it will throw an error saying "Unexpected end of JSON input", meaning, I'm parsing an incomplete JSON data.
Next step I did is, parse the data WHEN the data stream is done by specifying the "end".
Hope this helped.
Upvotes: 1
Reputation: 1160
In case of large json object you would want to parse the data in chunks.
Receive all the chunks on data
event and club the data from as soon as it arrives and parse the concatenated json on the end
event
const express = require("express");
const app = express();
const body = require("body-parser");
const https = require("https");
app.get("/results", function (req, res) {
https.get("https://www.omdbapi.com/?apikey=d49698c3&s=harry", function (response) {
let finalData = '';
response.on("data", function (data) {
finalData += data.toString();
});
response.on("end", function() {
const parsedData = JSON.parse(finalData);
res.send(parsedData.Title);
}
})
});
app.listen(3000)
Upvotes: 5