Unexpected end of JSON input when JSON is valid

Issue

I am using express to get data from a public API and use the data in my front end.

This is my characters route which works fine on certain Public API URLs, but most that I try ends up in an unexpected end of input error.

I am also getting an
Unexpected token , in JSON at position 48. How can this happen when it appears to be valid JSON?

const express = require('express'); // Web Framework
const https = require('https');
const router = express.Router();

const api = 'https://www.cheapshark.com/api/1.0/games?title=batman&steamAppID=35140&limit=60&exact=0';

router.get("/", function(req, res) {
    https.get(api, (response) => {
        console.log(response.statusCode);
        
        response.on('data', (d) => {
            try{
            const data = JSON.parse(d);
            console.log(data);
            res.send(data);
            } catch (err) {
                console.log(err);
            }
        })

        // res.send("Running")
    })
})

module.exports = router;

This is my index.js which uses the character route

const express = require('express'); // Web Framework
const app = express();
const PORT = 3000;

const charactersRoute = require('./routes/characters');


//Characters Route
app.use('/characters', charactersRoute)

app.listen(PORT, function(err) {
    if(err) console.log(err);
    console.log(`Server is listening on port ${PORT}`)
})

This is the JSON I am trying to parse. I validated this is valid JSON on those JSON validation sites.

[
    {
        "gameID": "146",
        "steamAppID": "35140",
        "cheapest": "14.95",
        "cheapestDealID": "LNCZ5EicmEMiwyfYVw%2FNdGPos9V7MzoPId2UuwaBqvA%3D",
        "external": "Batman: Arkham Asylum Game of the Year Edition",
        "internalName": "BATMANARKHAMASYLUMGAMEOFTHEYEAREDITION",
        "thumb": "https://cdn.cloudflare.steamstatic.com/steam/apps/35140/capsule_sm_120.jpg?t=1634156906"
    }
]

Solution

https response is a stream that returns chunks of data in the data event, so you need to concatenate data there (store buffer raw data into an array), and parse it in the .end event, when the response is finished, and then you can use res.json to send it to the consumer:

try this:

const express = require('express'); // Web Framework
const https = require('https');
const router = express.Router();

const api = 'https://www.cheapshark.com/api/1.0/games?title=batman&steamAppID=35140&limit=60&exact=0';

router.get("/", function(req, res) {

    https.get(api, (response) => {
        console.log(response.statusCode);

        const resData = [];

        response.on('data', (chunk) => {
            resData.push(chunk);
        });

        response.on('end', function() {

            try {
                const data = JSON.parse(Buffer.concat(resData).toString());
                console.log(data);
                res.json(data);
            } catch (err) {
                console.log(err);
            }
        });
    })
});

module.exports = router;

Answered By – traynor

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published