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]
复制到剪贴板
- 首先,我们有变量名称 — 。
superHeroes
- 在里面,我们想要访问该属性,因此我们使用.
members
["members"]
-
members
包含由对象填充的数组。我们想要访问数组中的第二个对象,因此我们使用 .[1]
- 在此对象内部,我们希望访问该属性,因此我们使用 。
powers
["powers"]
- 属性内部是一个数组,其中包含所选英雄的超能力。我们想要第三个,所以我们使用.
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 操作来显示它,如下所示:
顶级功能
顶级函数如下所示:
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:
- 我们声明变量来存储 GitHub URL
requestURL
- 我们使用 URL 来初始化新的请求对象。
- 我们使用fetch() 函数发出网络请求,这返回一个Response 对象
- 我们使用对象的 json() 函数将响应检索为 JSON。
Response
注意:该 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...的循环以循环遍历数组中的每个对象。对于每一个,我们:
- 创建几个新元素:一个 、一个、一个、三个 s 和一个 .
<article>
<h2>
<p>
<ul>
- 将 设置为包含当前英雄的 .
<h2>
name
- 用他们的 、和一行“超级大国:”填充这三个段落,以介绍列表中的信息。
secretIdentity
age
- 将属性存储在另一个名为 — 的新常量中 ,该常量包含一个列出当前英雄超能力的数组。
powers
superPowers
- 使用另一个循环来循环当前英雄的超能力 - 对于每个循环,我们创建一个元素,将超能力放入其中,然后将元素()放入内部。
for...of
<li>
listItem
<ul>
myList
appendChild()
- 我们要做的最后一件事是将 、 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对象在浏览器中可用,其中包含以下两种方法:
- parse():接受 JSON 字符串作为参数,并返回相应的 JavaScript 对象。
- stringify():接受对象作为参数,并返回等效的 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()