Learn web development

Working with JSON data

JavaScript对象表示法(JSON)是用于将结构化数据表示为JavaScript对象的标准格式,通常用于在网站上表示和传输数据 (i.e. 从服务器向客户端发送一些数据,因此可以将其显示在网页上). 您会经常遇到它,所以在本文中,我们向您提供使用JavaScript处理JSON的所有工作,包括访问JSON对象中的数据项并编写自己的JSON。

前提: 计算机基础知识,HTML 和 CSS 基础 (see First steps and Building blocks) 和 JS 面向对象基础(see Introduction to objects)。
目标: 理解 JSON 的数据储存工作原理,创建你的 JSON 对象。

不,说真的,什么是 JSON?

JSON 是一种按照JavaScript对象语法的数据格式,这是 Douglas Crockford 推广的。虽然它是基于 Javascript 语法,但它独立于javaScript,这也是为什么许多程序环境能够读取(解读)和生成 JSON。 

JSON可以作为一个对象或者字符串存在,前者用于解读 JSON 中的数据,后者用于通过网络传输 JSON 数据。 这不是一个大事件——JavaScript 提供一个全局的 可访问的 JSON 对象来对这两种数据进行转换。

一个 JSON 对象可以被储存在它自己的文件中,这基本上就是一个文本文件,扩展名为 .json, 还有 MIME type 用于 application/json.

JSON 结构

我们已经可以推测出 JSON 对象就是基于 Javascript 对象,而且这几乎是正确的。你可以把 JavaScript 对象原原本本的写入 JSON 数据——字符串,数字,数组,布尔还有其它的字面值对象。这允许你构造出一个对象树,如下:

{
  "squadName" : "Super hero squad",
  "homeTown" : "Metro City",
  "formed" : 2016,
  "secretBase" : "Super tower",
  "active" : true,
  "members" : [
    {
      "name" : "Molecule Man",
      "age" : 29,
      "secretIdentity" : "Dan Jukes",
      "powers" : [
        "Radiation resistance",
        "Turning tiny",
        "Radiation blast"
      ]
    },
    {
      "name" : "Madame Uppercut",
      "age" : 39,
      "secretIdentity" : "Jane Wilson",
      "powers" : [
        "Million tonne punch",
        "Damage resistance",
        "Superhuman reflexes"
      ]
    },
    {
      "name" : "Eternal Flame",
      "age" : 1000000,
      "secretIdentity" : "Unknown",
      "powers" : [
        "Immortality",
        "Heat Immunity",
        "Inferno",
        "Teleportation",
        "Interdimensional travel"
      ]
    }
  ]
}

如果我们要加载对象进入 Javascript 程序,以保存为一个名为 superHeroes 对象为例,我们使用 . 或 [] 访问对象内的数据(关于. 和 []概念,见 对象基础 )。例如:

superHeroes.hometown
superHeroes["active"]

为了访问对象中的对象,你只需简单地链式访问(通过属性名和数组索引)。例如,访问 superHeroes 对象中的 members 数组对象的第二个元素的 powers 数组对象的第三个元素,你可以这样做:

superHeroes["members"][1]["powers"][2]
  1. 首先我们有变量名 superHeroes,储存对象 。
  2. 在对象中我们想访问 members 属性,所以我们使用 ["members"].
  3. members 包含有对象数组,我们想要访问第二个元素,所以我们使用 [1].
  4. 在对象内,我们想访问 powers 属性,所以我们使用 ["powers"].
  5.  powers 属性是一个包含英雄技能的数组。我们想要第三个,所以我们使用[2].

注:我们已经在 JSONText.html 实例中让JSON 对象进入变量中使其可访问(see the source code)。尝试加载它并且在您的浏览器上访问对象数据。

JSON 数组

前面我们已经说过,”我们已经可以推测出 JSON 对象就是基于 Javascript 对象,而且这几乎是正确的“——我们说几乎正确的原因是数组对象也是一种合法的 JSON 对象,例如:

[
  {
    "name" : "Molecule Man",
    "age" : 29,
    "secretIdentity" : "Dan Jukes",
    "powers" : [
      "Radiation resistance",
      "Turning tiny",
      "Radiation blast"
    ]
  },
  {
    "name" : "Madame Uppercut",
    "age" : 39,
    "secretIdentity" : "Jane Wilson",
    "powers" : [
      "Million tonne punch",
      "Damage resistance",
      "Superhuman reflexes"
    ]
  }
]

上面是完全合法的 JSON。你只需要通过数组索引就可以访问数组元素,如[0]["powers"][0]。

 

其他注意事项

  • JSON 是一种纯数据格式,它只包含属性,没有方法。
  • JSON 要求有两头的 { } 来使其合法。最安全的写法是有两边的括号,而不是一边。
  • 甚至一个错位的逗号或分号就可以导致  JSON 文件出错。你应该小心的检查你想使用的数据(虽然计算机生成的 JSON 很少出错,只要生成程序正常工作)。你可以通过像 JSONLint 的应用程序来检验 JSON。
  • JSON 可以将任何标准合法的 JSON 数据格式化保存,不只是数组和对象。比如,一个单一的字符串或者数字可以是合法的 JSON 对象。虽然不是特别有用处……
  • 不像 JavaScript 标识符可以用作属性,在 JSON 中,只有字符串才能用作属性。

积极学习 : 一个JSON 示例

好了,让我们通过运行这个示例来展示我们如何利用JSON数据。

开始吧

首先,拷贝我们的 heroes.html 和 style.css 文件。后者包含了用于页面的简单的 CSS ,前者包含了简单的 HTML  body。

<header>
</header>
<section>
</section>

添加 <script>元素来包含我们的 JavaScript 代码。当前它只有两行,获得了<header> 和 <section> 的引用,保存在变量中。

var header = document.querySelector('header');
var section = document.querySelector('section');

我们已经把 JSON 数据放在了GitHub 上面 https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json

我们准备把它加载到我们的页面中,然后使用漂亮的 DOM 操作来展示它,就像这样:

加载我们的JSON

为了载入 JSON 到页面中,我们将使用 一个名为 XMLHttpRequest 的API(常称为XHR)。这是一个非常有用的 JavaScript 对象,使我们能够通过代码来向服务器请求资源文件(如:图片,文本,JSON,甚至HTML片段),意味着我们可以更新小段内容而不用重新加载整个页面。这将有更多响应页面,听起来让人兴奋,但是这部分超出我们本部分的文章,所以就不多详述了。

  1. 首先,我们将保存一个即将访问的 URL 作为变量。在你的 JavaScript 代码的底部添加下面的代码: 
    var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
  2. 为了创建一个Http请求,我们需要创建一个Http请求对象,通过 new 构造函数的形式。在你最下面的代码中写入:
    var request = new XMLHttpRequest();
  3. 现在我们需要使用 open() 函数打开一个新的请求,添加如下代码:
    request.open('GET', requestURL);

    这个函数至少含有两个参数,其它的是可选参数。对于示例我们只需要两个强制参数

    • HTTP 方法,网络连接时使用。这个示例中 GET 就可以了,因为我们只要获得简单的数据。
    • URL,用于指向请求的地址。我们使用之前保存的变量。
  4. 接下来,添加,两行代码,我们设定 responseType 为 JSON,所以服务器将知道我们想要返回一个 JSON 对象,然后发送请求 :
    request.responseType = 'json';
    request.send();
  5. 最后一点内容涉及相应来自服务器的返回数据,然后处理它,添加如下代码在你先前的代码下方:
    request.onload = function() {
      var superHeroes = request.response;
      populateHeader(superHeroes);
      showHeroes(superHeroes);
    }

这儿我们保存了相应我们请求的数据(访问 response 属性) 于变量 superHeroes ;这个变量现在含有 JSON!我们现在把 superHeroes 传给两个函数,第一个函数将会用正确的数据填充<header>,同时第二个函数将创建一个信息卡片,然后把它插入<section>中。

我们把代码包在事件处理函数中,当请求对象 load 事件触发时执行代码(onload),这是因为请求对象 load 事件只有在请求成功时触发;这种方式可以保证事件触发时 request.response 是绝对可以访问的。

定位 header

现在我们已经获得我们的JSON数据,让我们利用它来写两个我们使用的函数。首先,添加下面的代码于之前的代码下方:

function populateHeader(jsonObj) {
  var myH1 = document.createElement('h1');
  myH1.textContent = jsonObj['squadName'];
  header.appendChild(myH1);
  var myPara = document.createElement('p');
  myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' + jsonObj['formed'];
  header.appendChild(myPara);
}

我们称参数为 jsonObj,那也是为什么我们要在其中调用 JSON 对象。这儿我们首先使用 createElement() 创建了一个 <h1> 节点,将它的 textContent 设为 JSON 对象的 squadName 属性,然后通过 appendChild() 把它加入 <header>中。然后我们对段落做了相同的一件事情:创建,设置内容,追加到 <header>。唯一的不同在于它的内容设为一个与 JSON 内属性 homeTown formed 相关联的字符串。

创建英雄信息卡片

接下来,添加如下的函数到脚本代码底部,这个函数创建和展示了 superhero cards:

function showHeroes(jsonObj) {
  var heroes = jsonObj['members'];
  for(i = 0; i < heroes.length; i++) {
    var myArticle = document.createElement('article');
    var myH2 = document.createElement('h2');
    var myPara1 = document.createElement('p');
    var myPara2 = document.createElement('p');
    var myPara3 = document.createElement('p');
    var myList = document.createElement('ul');
    myH2.textContent = heroes[i].name;
    myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity;
    myPara2.textContent = 'Age: ' + heroes[i].age;
    myPara3.textContent = 'Superpowers:';
    var superPowers = heroes[i].powers;
    for(j = 0; j < superPowers.length; j++) {
      var listItem = document.createElement('li');
      listItem.textContent = superPowers[j];
      myList.appendChild(listItem);
    }
    myArticle.appendChild(myH2);
    myArticle.appendChild(myPara1);
    myArticle.appendChild(myPara2);
    myArticle.appendChild(myPara3);
    myArticle.appendChild(myList);
    section.appendChild(myArticle);
  }
}

首先,我们保存了 JSON 的 members 属性作为一个变量。这个数组含有多个带有英雄信息的对象。

接下来,我们使用一个循环来,遍历每个元素。对于每一个元素,我们:

  1. 创建几个元素: 一个 <article>,一个 <h2>, 三个 <p>s, 和一个 <ul>。
  2. 设置 <h2> 为当前英雄的 name。
  3. 使用他们的secretIdentity, age, "Superpowers:" 介绍信息列表 填充三个段落来。
  4. 保存 powers 属性于另一个变量 superPowers,包含英雄的superpowers列表。
  5. 使用另一个循环来遍历当前的英雄的 superpowers ,对于每一个元素我们创建<li>元素,把superpower 放进去,然后使用appendChild()把 listItem 放入<ul> 元素中。
  6. 最后一件事情是追加<h2>,<p>,还有<ul>进入 <article> (myArticle)。然后将<article> 追加到 <section>。追加的顺序很重要,因为他们将被展示在 HTML 中。

Note: 如有疑难,试试引用我们的 heroes-finished.html 代码(也可见 running live )。

Note: 如果你对访问 JSON对象的 点/括号标记 有困扰。获得文件 superheroes.json 并在你的编辑器中打开参考我们的 JS 代码将会有帮助。您还应该参考我们的 JavaScript object basics文章,了解关于点和括号符号的更多信息。

对象和文本间的转换

上述示例就访问 JSON 而言是简单的,因为我们设置了 XHR 来访问 JSON 格式数据: 

request.responseType = 'json';

但是有时候我们没有那么幸运,我们接收到一些 字符串作为 JSON 数据,然后我们想要将它转换为对象。当我们想要发送 JSON 数据作为信息,我们将需要转换它为字符串,我们经常需要正确的转换数据,幸运的是,这两个问题在web环境中是那么普遍以至于浏览器拥有一个内建的 JSON,包含以下两个方法。

  • parse(): 接收一个字符串最为参数,返回一个对应的对象。
  • stringify(): 接收一个JSON对象作为参数,返回一个对应的字符串。

你可以看看我们 heroes-finished-json-parse.html 示例的第一个操作 (见 source code) ,除了返回的是 text,这做了一件与我们之前一摸一样的事情,然后使用 parse() 来将他转换成为 JSON 对象。关键片段如下:

request.open('GET', requestURL);
request.responseType = 'text'; // now we're getting a string!
request.send();
request.onload = function() {
  var superHeroesText = request.response; // get the string from the response
  var superHeroes = JSON.parse(superHeroesText); // convert it to an object
  populateHeader(superHeroes);
  showHeroes(superHeroes);
}

正如你所想, stringify() 做相反的事情. 尝试将下面的代码输入你的浏览器 JS 控制台来看看会发生什么:

var myJSON = { "name" : "Chris", "age" : "38" };
myJSON
var myString = JSON.stringify(myJSON);
myString

这儿我们创建了一个JSON 对象,然后检查了它包含了什么,然后用stringify() 将它转换成字符串,最后保存返回值作为变量。然后再一次检查。

总结

在这个文章中,我们给了你一个简单的示例来在自己的程序中使用 JSON,包括创建和处理 JSON,还有如何访问 JSON 内的数据。在下一篇文章中我们将开始关注JS中的面向对象内容。

See also

文档标签和贡献者