JavaScript 对象表示法 (JSON) 是一种基于文本的标准格式,用于表示基于 JavaScript 对象语法的结构化数据。它通常用于在Web应用程序中传输数据(例如,将一些数据从服务器发送到客户端,因此它可以显示在网页上,反之亦然)。您经常会遇到它,因此在本文中,我们为您提供了使用JavaScript使用JSON所需的所有内容,包括解析JSON以便可以访问其中的数据以及创建JSON。

先决条件:

基本的计算机知识,对HTML和CSS的基本理解,对JavaScript基础知识的熟悉程度(参见​​第一步​​​和构建块​)和OOJS基础知识(参见​​对象简介​​)。

目的:

了解如何使用存储在 JSON 中的数据,并创建自己的 JSON 字符串。

不,真的,什么是JSON?

JSON是一种基于文本的数据格式,遵循JavaScript对象语法,由Douglas Crockford推广。尽管它与JavaScript对象文字语法非常相似,但它可以独立于JavaScript使用,并且许多编程环境都具有读取(解析)和生成JSON的能力。

JSON 以字符串形式存在 — 当您想要通过网络传输数据时非常有用。当您想要访问数据时,需要将其转换为本机 JavaScript 对象。这不是一个大问题 - JavaScript提供了一个全局JSON对象,该对象具有可用于在两者之间转换的方法。

注意:将字符串转换为本机对象称为反序列化,而将本机对象转换为字符串以便可以通过网络传输称为序列化

JSON字符串可以存储在其自己的文件中,该文件基本上只是一个扩展名为 的文本文件,MIME类型为。​​.json​​​​application/json​

JSON 结构

如上所述,JSON是一个字符串,其格式非常类似于JavaScript对象文本格式。您可以在 JSON 中包含与在标准 JavaScript 对象中相同的基本数据类型 — 字符串、数字、数组、布尔值和其他对象文本。这允许您构造数据层次结构,如下所示:

{
"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程序中,然后将其解析为一个调用的变量,则可以使用我们在JavaScript对象基础知识文章中看到的相同点/括号表示法访问其中的数据。例如:​​superHeroes​

superHeroes.homeTown
superHeroes['active']

复制到剪贴板

若要进一步访问层次结构中的数据,必须将所需的属性名称和数组索引链接在一起。例如,要访问成员列表中列出的第二个英雄的第三个超能力,您需要执行以下操作:

superHeroes['members'][1]['powers'][2]

复制到剪贴板

  1. 首先,我们有变量名称 — 。​​superHeroes​
  2. 在里面,我们想要访问该属性,因此我们使用.​​members​​​​["members"]​
  3. ​members​​包含由对象填充的数组。我们想要访问数组中的第二个对象,因此我们使用 .​​[1]​
  4. 在此对象内部,我们希望访问该属性,因此我们使用 。​​powers​​​​["powers"]​
  5. 属性内部是一个数组,其中包含所选英雄的超能力。我们想要第三个,所以我们使用.​​powers​​​​[2]​

注意:我们已经在 JSONTest 示例中的变量中提供了上面看到的 JSON.html。尝试加载此内容,然后通过浏览器的 JavaScript 控制台访问变量内的数据。

作为 JSON 的数组

上面我们提到JSON文本基本上看起来像字符串中的JavaScript对象。我们还可以将数组与 JSON 相互转换。下面也是有效的 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文件出错,并且不起作用。您应该小心验证您尝试使用的任何数据(尽管只要生成器程序正常工作,计算机生成的JSON就不太可能包含错误)。您可以使用JSONLint 等应用程序验证 JSON。
  • JSON实际上可以采用任何数据类型的形式,这些数据类型可以包含在JSON中,而不仅仅是数组或对象。例如,单个字符串或数字将是有效的 JSON。
  • 与在对象属性可以不带引号的 JavaScript 代码中不同,在 JSON 中,只有带引号的字符串可以用作属性。

主动学习:通过 JSON 示例工作

因此,让我们通过一个示例来展示如何在网站上使用一些JSON格式的数据。

开始

首先,制作我们的.html​和​​样式的​​本地副本.css文件。后者包含一些简单的CSS来设置页面的样式,而前者包含一些非常简单的正文HTML,以及一个​​​<script>​​​元素来包含我们将在本练习中编写的JavaScript代码:

<header>

</header>

<section>

</section>

<script>

</script>

复制到剪贴板

我们已经在gitHub上提供了我们的JSON数据,​​https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json​​。

我们将 JSON 加载到我们的脚本中,并使用一些漂亮的 DOM 操作来显示它,如下所示:

使用JSON_字符串

顶级功能

顶级函数如下所示:

async function populate() {

const requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
const request = new Request(requestURL);

const response = await fetch(request);
const superHeroes = await response.json();

populateHeader(superHeroes);
populateHeroes(superHeroes);

}

复制到剪贴板

为了获取 JSON,我们使用一个名为 ​​Fetch​​ 的 API。这个API允许我们通过JavaScript发出网络请求,从服务器检索资源(例如图像,文本,JSON,甚至HTML片段),这意味着我们可以更新小部分内容,而无需重新加载整个页面。

在我们的函数中,前四行使用 Fetch API 从服务器获取 JSON:

注意:该 API 是异步的。我们将在下一个​​模块​​中学习很多关于异步函数的知识,但现在我们只想说,我们需要在使用 fetch API 的函数名称之前添加关键字 ​​​async​​​,并在调用任何异步函数之前添加关键字 ​​​await​​​。​​fetch()​

毕竟,该变量将包含基于 JSON 的 JavaScript 对象。然后,我们将该对象传递给两个函数调用 — 第一个函数调用用正确的数据填充,而第二个函数调用为团队中的每个英雄创建一个信息卡,并将其插入到 .​​superHeroes​​​​<header>​​​​<section>​

填充标头

现在我们已经检索了 JSON 数据并将其转换为 JavaScript 对象,让我们通过编写上面引用的两个函数来利用它。首先,在前面的代码下面添加以下函数定义:

function populateHeader(obj) {
const header = document.querySelector('header');
const myH1 = document.createElement('h1');
myH1.textContent = obj['squadName'];
header.appendChild(myH1);

const myPara = document.createElement('p');
myPara.textContent = `Hometown: ${obj['homeTown']} // Formed: ${obj['formed']}`;
header.appendChild(myPara);
}

复制到剪贴板

在这里,我们首先使用 ​​​createElement()​​​ 创建一个 ​​​<h1>​​​ 元素,将其 ​​​textContent​​​ 设置为等于对象的属性,然后使用 ​​​appendChild()​​​ 将其附加到标头。然后,我们对段落执行非常相似的操作:创建它,设置其文本内容并将其附加到标题。唯一的区别是其文本设置为包含对象的 和 属性的​​模板文本​​。​​squadName​​​​homeTown​​​​formed​

创建英雄信息卡

接下来,在代码底部添加以下函数,该函数将创建并显示超级英雄卡牌:

function populateHeroes(obj) {
const section = document.querySelector('section');
const heroes = obj['members'];

for (const hero of heroes) {
const myArticle = document.createElement('article');
const myH2 = document.createElement('h2');
const myPara1 = document.createElement('p');
const myPara2 = document.createElement('p');
const myPara3 = document.createElement('p');
const myList = document.createElement('ul');

myH2.textContent = hero.name;
myPara1.textContent = `Secret identity: ${hero.secretIdentity}`;
myPara2.textContent = `Age: ${hero.age}`;
myPara3.textContent = 'Superpowers:';

const superPowers = hero.powers;
for (const power of superPowers) {
const listItem = document.createElement('li');
listItem.textContent = power;
myList.appendChild(listItem);
}

myArticle.appendChild(myH2);
myArticle.appendChild(myPara1);
myArticle.appendChild(myPara2);
myArticle.appendChild(myPara3);
myArticle.appendChild(myList);

section.appendChild(myArticle);
}
}

复制到剪贴板

首先,我们将 JavaScript 对象的属性存储在一个新变量中。此数组包含多个对象,这些对象包含每个英雄的信息。​​members​

接下来,我们使用一个 ​​for...的循环​​以循环遍历数组中的每个对象。对于每一个,我们:

  1. 创建几个新元素:一个 、一个、一个、三个 s 和一个 .​​<article>​​​​<h2>​​​​<p>​​​​<ul>​
  2. 将 设置为包含当前英雄的 .​​<h2>​​​​name​
  3. 用他们的 、和一行“超级大国:”填充这三个段落,以介绍列表中的信息。​​secretIdentity​​​​age​
  4. 将属性存储在另一个名为 — 的新常量中 ,该常量包含一个列出当前英雄超能力的数组。​​powers​​​​superPowers​
  5. 使用另一个循环来循环当前英雄的超能力 - 对于每个循环,我们创建一个元素,将超能力放入其中,然后将元素()放入内部。​​for...of​​​​<li>​​​​listItem​​​​<ul>​​​​myList​​​​appendChild()​
  6. 我们要做的最后一件事是将 、 s 和 () 内部追加,然后将 内加 。内容的追加顺序很重要,因为这是它们在 HTML 中的显示顺序。​​<h2>​​​​<p>​​​​<ul>​​​​<article>​​​​myArticle​​​​<article>​​​​<section>​

注意:如果您在使示例正常工作时遇到问题,请尝试参考我们的​​完成的.html​​​源代码(另请参阅它​​实时运行​​)。

注意:如果您在遵循我们用于访问JavaScript对象的点/括号表示法时遇到问题,那么在另一个选项卡或文本编辑器中打开​​superheromes.json​​文件并在需要时引用它会有所帮助。您还应该参考我们的 JavaScript 对象基础知识文章,了解有关点和括号表示法的更多信息。

调用顶级函数

最后,我们需要调用我们的顶级函数:​​populate()​

populate();

复制到剪贴板

在对象和文本之间转换

上面的例子在访问JavaScript对象方面很简单,因为我们使用将网络响应直接转换为JavaScript对象。​​response.json()​

但有时我们并不那么幸运 - 有时我们会收到一个原始的JSON字符串,我们需要自己将其转换为对象。当我们想通过网络发送JavaScript对象时,我们需要在发送之前将其转换为JSON(字符串)。幸运的是,这两个问题在Web开发中非常普遍,以至于内置的​​JSON​​对象在浏览器中可用,其中包含以下两种方法:

您可以在我们的​​hero-finish-json-parse.html​​示例中看到第一个操作 - 这与我们之前构建的示例完全相同,除了:

  • 我们通过调用响应的 text​​​()​​​ 方法将响应检索为文本而不是 JSON
  • 然后,我们使用将文本转换为JavaScript对象。​​parse()​

代码的关键片段如下:

async function populate() {

const requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
const request = new Request(requestURL);

const response = await fetch(request);
const superHeroesText = await response.text();

const superHeroes = JSON.parse(superHeroesText);
populateHeader(superHeroes);
populateHeroes(superHeroes);

}

复制到剪贴板

正如您可能猜到的那样,工作方式恰恰相反。尝试在浏览器的 JavaScript 控制台中逐个输入以下行,以查看其运行情况:​​stringify()​

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

复制到剪贴板

在这里,我们创建一个JavaScript对象,然后检查它包含的内容,然后使用它转换为JSON字符串 - 将返回值保存在新变量中 - 然后再次检查它。​​stringify()​