Home > Enterprise >  Parsing JSON error cannot read property 'url' of undefined
Parsing JSON error cannot read property 'url' of undefined

Time:10-23

I have been trying to parse JSON, which have 3 different set of data where one element have various number of children and sometimes none. I am getting an error when there is no children present or only one present. I declared the JSON as var data.

JSON A

{
  "floorplan": [
    {
      "title": "plan1",
      "url": "https://media.plan1.pdf"
    },
    {
      "title": "plan2",
      "url": "https://media.plan2.pdf"
    }
  ]
}

JSON B

{"floorplan": []}

JSON C

{
  "floorplan": [
    {
      "title": "plan1",
      "url": "https://media.plan1.pdf"
    }
  ]
}

I parsed the JSON like this:

var items = JSON.parse(data);
return {
    floorplan1: items.floorplan[0].url;
    floorplan2: items.floorplan[1].url;
}

But, it only returned data for the JSON A, for other 2 it gave TypeError: Cannot read property 'url' of undefined.

I modified the code to check if floorplan have at least one child and then parse data.

var items = JSON.parse(data);
var plan = items.floorplan[0];
if(plan){
    return {
        floorplan1: items.floorplan[0].url;
        floorplan2: items.floorplan[1].url;
    }
}

The new code returned data for JSON A and B(as empty row), but gave error for C. C have one child still it got the error.

I also tried this code, still got the error for JSON C.

    var items = JSON.parse(data);
    var plan = items.floorplan[0];
    var plan1;
    var plan2;
    if(plan){
            plan1 = items.floorplan[0].url;
            plan2 = items.floorplan[1].url;
        }
    return{
          floorplan1 : plan1 ? plan1 : null;
          floorplan2 : plan2 ? plan2 : null;
    }

Is there any method I can try to get data returned for all 3 types of JSON?

CodePudding user response:

let data = `
[{"floorplan": [{
  "title": "plan1",
  "url": "https://media.plan1.pdf"
}, {
  "title": "plan2",
  "url": "https://media.plan2.pdf"
}]}, 
{"floorplan": []},
{"floorplan": [{
  "title": "plan1",
  "url": "https://media.plan1.pdf"
}]}]`;

let json = JSON.parse(data);
//console.log(json);

json.forEach(items=>{
  //console.log(items);
  
  let o = {
    floorplan1: items.floorplan.length > 0 ? items.floorplan[0].url : '',
    floorplan2: items.floorplan.length > 1 ? items.floorplan[1].url : ''
  };
  console.log(o);
  
  o = {
    floorplan1: (items.floorplan[0] || {'url':''}).url,
    floorplan2: (items.floorplan[1] || {'url':''}).url
  };
  console.log(o);
  
  o = {
    floorplan1: items.floorplan[0]?.url,
    floorplan2: items.floorplan[1]?.url
  };
  console.log(o);
  
  const {floorplan: [one = {url:''}, two = {url:''}]} = items;
  o = {
    floorplan1: one.url,
    floorplan2: two.url
  };
  console.log(o);
  
});
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Sure. A few ways, and more than I have here. I have put all the raw data into one string, parsed it into json and then iterated through that. In each loop my variable items will correspond to one of the json variables you created and referenced in your question as items.

In the first example, I check to make sure that items.floorplan has at least enough elements to contain the url I'm trying to reference, then use the ternary operator ? to output that URL if it exists or an empty string if it doesn't.

In the second example, I use the || (OR) operator to return the first object that evaluates to true. If items.floorplan[x] exists, then it will be that node, and if it doesn't I provide a default object with an empty url property on the right hand side, and then just use the url from the resulting object.

In the third, I use the optional chaining operator that was introduced in 2020. This method will return undefined if the url doesn't exist.

In the fourth example, I use destructuring to pull values out of the items variable, and make sure that there is a default value for url in case the items variable doesn't have a corresponding value.

But there are many more ways to go about it. These are just a few, and you can't necessarily say which approach is better. It's dependent on your intent and environment. With the exception of optional chaining (which shows undefined if the property doesn't exist), you can see these produce the same results.

DOCS for optional chaining: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

DOCS for destructuring: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

An article on destructuring: https://javascript.info/destructuring-assignment

  • Related