首页 > 解决方案 > 解析 JSON 错误无法读取未定义的属性“url”

问题描述

我一直在尝试解析 JSON,它有 3 组不同的数据,其中一个元素有不同数量的子元素,有时没有。当没有孩子在场或只有一个孩子在场时,我收到错误消息。我将 JSON 声明为 var 数据。

一个JSON

{
  "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"
    }
  ]
}

我像这样解析JSON:

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

但是,它只返回 JSON A 的数据,对于其他 2,它给出了TypeError: Cannot read property 'url' of undefined。

我修改了代码以检查平面图是否至少有一个孩子,然后解析数据。

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

新代码返回了 JSON A 和 B 的数据(作为空行),但给 C 带来了错误。C 有一个孩子仍然得到错误。

我也试过这段代码,仍然得到 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;
    }

有什么方法可以尝试为所有 3 种 JSON 类型返回数据?

标签: jsonparsingundefinedjsonparser

解决方案


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);
  
});

当然。有几种方法,比我这里更多。我已将所有原始数据放入一个字符串中,将其解析为json然后对其进行迭代。在每个循环中,我的变量items将对应于您在问题中创建和引用的 json 变量之一items

在第一个示例中,我检查以确保 items.floorplan 至少有足够的元素来包含我要引用的 url,然后使用三元运算符 ? 如果该 URL 存在则输出该 URL,如果不存在则输出一个空字符串。

在第二个示例中,我使用 || (OR) 运算符返回第一个计算结果为 true 的对象。如果 items.floorplan[x] 存在,那么它将是那个节点,如果不存在,我会在右侧提供一个带有空 url 属性的默认对象,然后只使用结果对象中的 url。

第三,我使用了 2020 年引入的可选链操作符。如果 url 不存在,该方法将返回 undefined。

在第四个示例中,我使用解构从 items 变量中提取值,并确保 url 有一个默认值,以防 items 变量没有相应的值。

但是还有更多的方法可以解决这个问题。这些只是其中的几个,你不一定能说哪种方法更好。这取决于您的意图和环境。除了可选链接(如果属性不存在则显示未定义),您可以看到这些产生相同的结果。

用于可选链接的文档:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

解构文档:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

一篇关于解构的文章:https ://javascript.info/destructuring-assignment


推荐阅读