Home > Software design >  Unexpected end of json input in nodejs using unsplash api
Unexpected end of json input in nodejs using unsplash api

Time:06-28

i am using unsplash api in Nodejs when i recive data from API I try to parse the data but i am getting the error unexpected end of json.


code:

        const express = require("express");
        const https = require("https");
        const app = express();
        const port = 4000;
//      app.use(express.urlencoded({ extended: true }));
        app.use(express.static("public"));
        app.set("view engine", "ejs");
        app.get("/", (req, res) => {
      
          const url ="https://api.unsplash.com/photos/?client_id=ipLjiRmWcJ-jWn5uG8UhibNGiFgHxTVE_KeHHb8Oo3M";
          https.get(url, (response) => {
           status_code = response.statusCode;
           if (status_code == 200) {
             try {
              response.on("data", (data) => {
               var data_str = data.toString();

               console.log(JSON.parse(data_str));
             });
          } catch (error) {
            console.log(error);
          }
              res.send();
        }
      });
    });

    app.listen(port, () => console.log(`connected to port: ${port}`));

============================================================


error: [enter image description here][1]


undefined:1
[{"id":"3f04FMm_Jqk","created_at":"2022-03-31T10:33:43-04:00","updated_at":"2022-06-25T17:25:36-04:00","promoted_at":null,"width":6048,"height":4024,"color":"#8c8c73","blur_hash":"LLE2nHWB0KVse.ozIoxaM{i_s:S4","description":null,"alt_description":null,"urls":{"raw":"https://images.unsplash.com/photo-1648737119359-510d4f551382?ixid=MnwzNDEyNDR8MXwxfGFsbHwxfHx8fHx8Mnx8MTY1NjI2NjU2OQ\u0026ixlib=rb-1.2.1","full":"https://images.unsplash.com/photo-1648737119359-510d4f551382?crop=entropy\u0026cs=tinysrgb\u0026fm=jpg\u0026ixid=MnwzNDEyNDR8MXwxfGFsbHwxfHx8fHx8Mnx8MTY1NjI2NjU2OQ\u0026ixlib=rb-1.2.1\u0026q=80","regular":"https://images.unsplash.com/photo-1648737119359-510d4f551382?crop=entropy\u0026cs=tinysrgb\u0026fit=max\u0026fm=jpg\u0026ixid=MnwzNDEyNDR8MXwxfGFsbHwxfHx8fHx8Mnx8MTY1NjI2NjU2OQ\u0026ixlib=rb-1.2.1\u0026q=80\u0026w=1080","small":"https://images.unsplash.com/photo-1648737119359-510d4f551382?crop=entropy\u0026cs=tinysrgb\u0026fit=max\u0026fm=jpg\u0026ixid=MnwzNDEyNDR8MXwxfGFsbHwxfHx8fHx8Mnx8MTY1NjI2NjU2OQ\u0026ixlib=rb-1.2.1\u0026q=80\u0026w=400","thumb":"https://images.unsplash.com/photo-1648737119359-510d4f551382?crop=entropy\u0026cs=tinysrgb\u0026fit=max\u0026fm=jpg\u0026ixid=MnwzNDEyNDR8MXwxfGFsbHwxfHx8fHx8Mnx8MTY1NjI2NjU2OQ\u0026ixlib=rb-1.2.1\u0026q=80\u0026w=200","small_s3":"https://s3.us-west-2.amazonaws.com/images.unsplash.com/small/pho

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at IncomingMessage.<anonymous> (C:\Users\Muslim Shah\Documents\express\unsplash\app.js:19:28)
    at IncomingMessage.emit (node:events:527:28)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at IncomingMessage.Readable.push (node:internal/streams/readable:228:10)
    at HTTPParser.parserOnBody (node:_http_common:141:24)
    at TLSSocket.socketOnData (node:_http_client:494:22)
    at TLSSocket.emit (node:events:527:28)
    at addChunk (node:internal/streams/readable:315:12)
[nodemon] app crashed - waiting for file changes before starting...

what I tried I tried to convert the data into string first then parse it but the error was the same

CodePudding user response:

Diagnosis

Your handling of the response assumes that a single data event is fired that provides the complete response data.

However, this assumption would be incorrect. The stream.Readable class, of which the query response is a subclass instance, delivers content in chunks by repeatedly emitting data events. The end of a stream is signalled by a dedicated end event.

In consequence, response data first has to be collected and reassembled before passing it on to the JSON parser.

Code

Warning: This code is untested.

const express = require("express");
const https = require("https");
const app = express();
const port = 4000;
//      app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
app.set("view engine", "ejs");
app.get("/", (req, res) => {

    const url ="https://api.unsplash.com/photos/?client_id=ipLjiRmWcJ-jWn5uG8UhibNGiFgHxTVE_KeHHb8Oo3M";
    https.get(url, (response) => {
        status_code = response.statusCode;
        if (status_code == 200) {
            // Watch out here:
            //  - Response data is delivered in chunks
            //  - If your next processing step operates on the whole response data, you need to collect the chunks into one string first.
            //  - Your dat ais ready for further processing when the `end` event is received.
            //
            let data_complete = ''
              ;
              
            try {
                response.on("data", (data_chunk) => {
                    data_complete  = data_chunk.toString();
                });
                response.on("end", () => {
                    console.log(JSON.parse(data_complete));
                });
            } catch (error) {
                console.log(error);
            }
            res.send();
        }
   });
});

Note

There might be JSON parsers around that directly operate on streams. However, the basic code structure (data handler catering for repeated calls providing chunks of data, end handler to initiate next processing steps) wouldn't change

References

The node.js (v18.4.0) stream.Readable docs: https://nodejs.org/dist/latest-v18.x/docs/api/stream.html#class-streamreadable docs. Docs for other versions of node.js can be found by replacing the major version number in the link above (the basic mechanism underlying the effect you observed has not changed though)

  • Related