JavaScript Node.js Basics Handling Errors in Node Handling Parsing Errors with try and catch

Jeffrey Kwok
Jeffrey Kwok
3,006 Points

Trying to parse JSON file in node js but I get a "Cannot read property 'length' of undefined" error

Hi,

The title explains it all. The json file url and code is below. What I want to happen is for the "description object", "title object" and " downloadUrl object" to be printed out

Can anyone help?

URL: https://core.ac.uk/api-v2/articles/search/cells?page=1&pageSize=20&metadata=true&fulltext=false&citations=false&similar=false&duplicate=false&urls=true&faithfulMetadata=false&apiKey=XXXXXXXX

CODE:

const https = require('https');
const apikey = "XXXXXXXXX";


// Connect to the API URL
const request = https.get(`https://core.ac.uk/api-v2/articles/search/cells?page=1&pageSize=20&metadata=true&fulltext=false&citations=false&similar=
false&duplicate=false&urls=true&faithfulMetadata=false&apiKey=${apikey}`, response => {
    let body = "";
// Read the data
response.on('data', data => {
    body += data.toString();
});

response.on('end', () => {
    // Parse the data
    const profile = JSON.parse(body);
// Print the data
// console.dir(profile);
});
var json = body;
    for(var i = 0; i < json.line.length; i++)
    {
        console.dir(" Description: " + json.line[i].description + " title: " + json.line[i].title + " downloadUrl: " + json.line[i].downloadUrl);
        //
    }

3 Answers

response.on('end') takes a callback which you have, but you need to put your json loop inside the 'end' event listener. like so:

response.on('end', () => {
    // Parse the data
    const profile = JSON.parse(body);
   // Print the data
  // console.dir(profile);
   var json = body;
   for(var i = 0; i < json.line.length; i++)
   {
       console.dir(" Description: " + json.line[i].description + " title: " + json.line[i].title + " downloadUrl: " 
 +json.line[i].downloadUrl);

   }
});

I have not tried running it, but the error you got means that line in json was not defined which makes sense if you have it on the outside of your 'end' listener.

Jeffrey Kwok
Jeffrey Kwok
3,006 Points

HI Alex,

Thank you for the reply. I tried what you recommended but I still get the same error. I think it might me because some of the "description" and "title" keys are null. Would that have an effect?

Hi Jeffrey,

No. Your problem is that the property 'line' is undefined. So json does not have a property named line. I know that because when I run the following code, it prints 'undefined'

const request = https.get(`https://core.ac.uk/api-v2/articles/search/cells?page=1&pageSize=20&metadata=true&fulltext=false&citations=false&similar=false&duplicate=false&urls=true&faithfulMetadata=false&apiKey=${apikey}`, (response) => {
    let body = "";
    response.on('data', data => {
        console.log('Reading Data');
        body += data.toString();
    });

    response.on('end', () => {
        // Parse the data
        const profile = JSON.parse(body);
        var json = body;
        console.log(json.line); //prints undefined. so you can't call json.line.length on it wihtout throwing an error
    });
});

What is the json strucutre looking like? How do you know you need to access the line property? If you can provide an example I may be able to help you out.

Jeffrey Kwok
Jeffrey Kwok
3,006 Points

Hi Alex,

Sorry to bug you again. I did try implementing "json.data" as you suggested but I'm still getting the same error. I made a genuine attempt to solve it by looking back on previous tutorials and looking through stackoverflow to no avail. Is there any other reason why the error keeps appearing? below is the code:

const request = https.get("https://core.ac.uk/api-v2/articles/search/cells?page=1&pageSize=20&metadata=true&fulltext=false&citations=false&similar=false&duplicate=false&urls=true&faithfulMetadata=false&apiKey=XXXXXXXXXX", (response) => {
    let body = "";
    response.on('data', data => {
        console.log('Reading Data');
        body += data.toString();
    });

    response.on('end', () => {
        // Parse the data
        const profile = JSON.parse(body);
        var json = body;
        console.log(json.data); //prints the data you want
        for(let i = 0; i<json.data.length;i++) {
            console.log(" description: " + json.data[i].description + " title: " + json.data[i].title + " downloadUrl: " + json.data[i].downloadUrl);
        }
    });
});

Hi Jeffrey,

Sorry I should have caught this yesterday already, but you pretty much do not need the line var json = body; As you are parsing the data with const profile = JSON.parse(body); Turning the body into json and assigning it to profile. Now you need to refer to profile then in your loop and not json. Like so:

response.on('end', () => {
        // Parse the data
        const profile = JSON.parse(body);
        var json = body; //THIS LINE IS NOT NEEDED ANYMORE
        console.log(profile);
        for(let i = 0; i<profile.data.length;i++) {
            console.log(" description: " + profile.data[i].description + " title: " + profile.data[i].title + " downloadUrl: " + profile.data[i].downloadUrl);
        }
    });

I actually tried it out this time lol and it works. It takes a few seconds for the response to come back though so be patient.

Jeffrey Kwok
Jeffrey Kwok
3,006 Points

Hi Alex,

the json fie is https://core.ac.uk/api-v2/articles/search/cells?page=1&pageSize=20&metadata=true&fulltext=false&citations=false&similar=false&duplicate=false&urls=true&faithfulMetadata=false&apiKey=PykSKLeJz7ZldYQbNWoTDvwCfnarFXOg

you may need to install a json viewer add on your browser so that its in a readable format

Basically, the key value pairs for "description", "title" , and "downloadUrl" are all nested in the "data" array of the json filee. Does that answer your question? Let me know if you need clarification.

Thanks. Yes so you need to loop over the json.data instead over the json.line.

const request = https.get(`https://core.ac.uk/api-v2/articles/search/cells?page=1&pageSize=20&metadata=true&fulltext=false&citations=false&similar=false&duplicate=false&urls=true&faithfulMetadata=false&apiKey=${apikey}`, (response) => {
    let body = "";
    response.on('data', data => {
        console.log('Reading Data');
        body += data.toString();
    });

    response.on('end', () => {
        // Parse the data
        const profile = JSON.parse(body);
        var json = body;
        console.log(json.line); //prints undefined. so you can't call json.line.length on it wihtout throwing an error
        console.log(json.data); //prints the data you want
        for(let i = 0; i<json.data.length;i++) {
              //do stuff with json.data[i].description etc. here
        }
    });
});
Jeffrey Kwok
Jeffrey Kwok
3,006 Points

Thanks for the help Alex! I appreciate it :)