1

I'm very new to this, I tried to look at other posts but I can't find the right answer. I'm using Node JS https to call an API to get status information on public transport. The response seems to be an array of Object but I don't seem to be able to parse it correctly.

This is my code:

//app set up
const express = require("express");
const https = require("https");
const bodyParser = require("body-parser");
const dotenv = require("dotenv").config();
const ejs = require("ejs");

const app = express();

app.use(express.static(__dirname + '/public'));
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended:true}));



 // get request to the page
app.get("/status", function(req,res){
    // get request to the API
 const url="https://api.tfl.gov.uk/Line/victoria/Status?app_id="+process.env.PRIMARY_KEY+"&app_key="+process.env.SECONDARY_KEY;
    
https.get(url, function(response){
        console.log (response);
        console.log(response.statusCode);
        console.log(response.headers);
        let responseBody = "";
        let parsedBody = [];
        response.setEncoding("utf-8");
        response.on("data", function(chunk){
            responseBody += chunk;
            console.log("this is the body response"+responseBody);
            console.log("this is the body response lenght"+responseBody.length);
            console.log("this is the body position 0 "+responseBody[0]);
            console.log("this is the body position 1 "+responseBody[1]);
        });     
        res.redirect("/");
});

The header returns this:

    {
  date: 'Sun, 08 Aug 2021 11:37:41 GMT',
  'content-type': 'application/json; charset=utf-8',
  'transfer-encoding': 'chunked',
  connection: 'close',
  'cache-control': 'public, must-revalidate, max-age=30, s-maxage=60',
  via: '1.1 varnish',
  age: '0',
  'access-control-allow-headers': 'Content-Type',
  'access-control-allow-methods': 'GET,POST,PUT,DELETE,OPTIONS',
  'access-control-allow-origin': '*',
  'api-entity-payload': 'Line,LineStatus',
  'x-backend': 'api',
  'x-cache': 'MISS',
  'x-cacheable': 'Yes. Cacheable',
  'x-frame-options': 'deny',
  'x-proxy-connection': 'unset',
  'x-ttl': '60.000',
  'x-ttl-rule': '0',
  'x-varnish': '935110596',
  'x-aspnet-version': '4.0.30319',
  'x-operation': 'Line_StatusByIdsByPathIdsQueryDetail',
  'x-api': 'Line',
  'cf-cache-status': 'DYNAMIC',
  'expect-ct': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"',
  server: 'cloudflare',
  'cf-ray': '67b874417d2b078e-LHR'
}

so it seems that the response is a JSON file -- right?

The responseBody looks like that:

[{"$type":"Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities","id":"victoria","name":"Victoria","modeName":"tube","disruptions":[],"created":"2021-08-05T16:15:46.917Z","modified":"2021-08-05T16:15:46.917Z","lineStatuses":[{"$type":"Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities","id":0,"statusSeverity":10,"statusSeverityDescription":"Good Service","created":"0001-01-01T00:00:00","validityPeriods":[]}],"routeSections":[],"serviceTypes":[{"$type":"Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities","name":"Regular","uri":"/Line/Route?ids=Victoria&serviceTypes=Regular"},{"$type":"Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities","name":"Night","uri":"/Line/Route?ids=Victoria&serviceTypes=Night"}],"crowding":{"$type":"Tfl.Api.Presentation.Entities.Crowding, Tfl.Api.Presentation.Entities"}}]

And if I assume it's an array of object and log its length and elements, I get this:

responseBody.length= 900
responseBody[0] = [
responseBody[1] = {

If I use responseBody += JSON.parse(chunk) I get an error:

undefined:1
[{"$type":"Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities","id":"victoria","name":"Victoria","modeName":"tube","disruptions":[],"created":"2021-08-05T16:15:46.917Z","modified":"2021-08-05T16:15:46.917Z","lineStatuses":[{"$type":"Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities","id":0,"statusSeverity":10,"statusSeverityDescription":"Good Service","created":"0001-01-01T00:00:00","validityPeriods":[]}],"routeSections":[],"serviceTypes":[{"$type":"Tfl.Api.Presentation.Entities
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at IncomingMessage.<anonymous> (C:\Users\THIS IS MY PATH\index.js:44:34)
    at IncomingMessage.emit (events.js:315:20)
    at IncomingMessage.Readable.read (internal/streams/readable.js:519:10)
    at flow (internal/streams/readable.js:992:34)
    at resume_ (internal/streams/readable.js:973:3)
    at processTicksAndRejections (internal/process/task_queues.js:80:21)

And if I use responseBody += JSON.parse(JSON.stringify(chunk)) I get again this

 responseBody.length= 900
    responseBody[0] = [
    responseBody[1] = {

Any suggestion? Am I getting the response in another format than JSON so I should transform it differently? or there is something wrong with my code? thank you

1 Answer 1

1

In the on("data") callback you receive chunks of data, so it only makes sense to juse JSON.parse after all the chunks have been assembled. So you should do something like this:

response.on("data", (chunk) => {
  responseBody += chunk;           
});  

response.on("end", () => {
  const parsedJson = JSON.parse(responseBody);
  console.log(parsedJson);
}); 

As a side note - there are many libraries you can use for http-requests that do this kinds of things out of the box, e.g. https://www.npmjs.com/package/node-fetch#json to name one.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.