全站通知:
帮助:使用JSON动态更新页面
刷
历
编
跳到导航
跳到搜索
须知
- 作者会尽量采用通俗的语言来介绍,但涉及到核心的部分依然需要你懂得一定的编程及前端知识。
- 本文中的代码块,绿色底表示正确,红色底表示错误,黄色底表示警告。
前言
什么是JSON
- JSON是JS通用的外部数据储存格式,其形式是对象或数组,形如:
{
"键": "值"
}
- 或
[ "值" ]
- 为了便于展示,本文大多数情况会采用对象作为示例,但你应该知道数组也是JSON中重要的形式,按照需求设计结构会让你事半功倍。
- 其实,数组本就是一种特殊的对象,数组的键就是元素的位置(index),这里不展开介绍了。
规范
根对象/根数组
- 一个JSON必须有且只有一个最外层对象/数组,就如同开篇的两个样例。
"无根的键": "值",
{
"键": "值"
}
{
"键": "值"
}
分隔
- 键与值之间必须使用英文冒号
:进行分隔。 - 一条内容之间必须使用英文逗号
,进行分隔,最后一条内容后不能加逗号。
{
"键1": "值1",
"键2": "值2"
}
{
"键1": "值1"
"键2": "值2"
}
{
"键1": "值1",
"键2": "值2",
}
格式化
- JSON对换行、缩进(空格/制表符)均没有要求:
{
"键1":
"值1",
"键2": "值2"
}
{
"键1":"值1",
"键2":"值2"
}
- 请不要学习以上两种写法。
{"键1":"值1","键2":"值2"}
- 以上便是压缩后的JSON。
(对象的)键
- 键必须是使用英文双引号
""包裹的字符串:
{
'单引号': "值"
}
- 在一个对象内,不能有同名的键:
{
"同名的键": "值1",
"同名的键": "值2"
}
值
- 值是可以重复的。
{
"键1": "值",
"键2": "值",
"键3": "值"
}
- 值可以储存以下数据:
字符串
{
"字符串": "你好,世界。"
}
- 字符串值和键一样,必须使用英文双引号
""包裹:
{
"字符串": '单引号,不行。'
}
数字
{
"整数": 5,
"浮点数": 3.1416,
"科学计数": 6.02e23
}
{
"其他进制表示法": 0xf2dede,
"极限值": Infinity
}
真假(布尔)
{
"布尔真": true,
"布尔假": false
}
空(null)
{
"空": null
}
对象/数组
{
"子对象": {
"子对象的键": "子对象的值"
},
"子数组": [
"子数组的值1",
"子数组的值2"
]
}
- 基于此特点,可以设计出复杂的结构来储存大量的数据:
{
"table": {
"id": null,
"class": ["wikitable","test"]
},
"headLine": [
"序号",
"事件",
"发生时间",
"是否完成"
],
"lines": [
[
1,
"起床",
1660608000000,
true
],
[
2,
"吃饭",
1660608900000,
true
],
[
3,
"上车",
1660609800000,
true
],
[
4,
"上班",
1660613400000,
true
],
[
5,
"下班",
1660645800000,
false
]
]
}
- 事实上,JSON可以不需要根,仅单独存一个值,但这几乎只在极少数情况下有用,本文之后也不会介绍。
- 其实,字符串、数字、布尔、空,也是特殊的对象,这里也不展开介绍了。
"值"
1
false
null
与JS对象的关系
- 在阅读本节内容之前,请你先复述这句话无数遍:
- JSON对于JS来说是字符串。
- JSON 对于JS来说 是字符串。
- JSON 对于 JS 来说是 字符串。
- 如果你无法理解这句话的含义,可能会对后续的阅读产生障碍。
- 当然,你也可以尝试带着疑问继续阅读。
互相转化
- JSON可以通过JS的函数
JSON.parse转为JS对象。
JSON.parse('{"键":"值"}')
//输出:一个JS对象
- 这个动作称为解析。
- JS对象可以通过JS的函数
JSON.stringify转为JSON。
let obj={
"键": "值"
}
JSON.stringify(obj)
//输出:'{"键":"值"}'
- 这个动作称为序列化。
不同点
- JSON无法储存JS对象中的函数,序列化一个含有函数的JS对象时,会被舍弃:
let obj={
键:"值",
函数:function(){
return "你好,世界。"
}
}
JSON.stringify(obj)
//输出:'{"键":"值"}'
- 总体来说,序列化一个JS对象时,只有 $值 中提到的类型可以保留,其他的可能变成空(null),可能被舍弃,也可能变成空对象:
let obj={
极限:Infinity,
标签:Symbol(),
DOM元素:document.createElement("div")
}
JSON.stringify(obj)
//输出:'{"极限":null,"DOM元素":{}}'
正文
- 在谷歌浏览器等现代浏览器中均可以在控制台中直接运行JS,如果方便的话,请你按下F12打开控制台,跟着作者一步步操作。
- 使用函数
console.log输出结果:
- 使用函数
console.log("你好,世界。")
//输出:你好,世界。
- 本文后续的所有的内容不再像 $与JS对象的关系 中直接输出结果了,而是通过
console.log输出结果。
读取JSON
- JSON最常见的形式有两种:静态文件(*.json)和请求结果(HttpRequest)。
- 前端实际操作都是通过让JS访问一个地址(URL),获取到了JSON的字符串,再将其解析为JS对象后使用。
访问地址(异步)
- 作者已经准备好了一个JSON,就放在 https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw 这里,你可以先通过浏览器直接看到它的内容。
原生JS
let url = "https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw"
let ajax = new XMLHttpRequest()
ajax.open("GET", url)
ajax.send()
let obj = JSON.parse(ajax.responseText)
console.log(obj)
//报错
- 为什么在控制台中没有结果?
- 原来这是一个异步操作。顾名思义,异步是不同步的,JS不会立刻执行异步操作中的代码,而是等待谁来告诉它“你可以继续了”才会继续执行。
- 在上述代码中,谁就是服务器。服务器把JSON发过来需要时间,虽然bilibili的服务器很快很快,但在你敲下回车的一瞬间,JS就已经执行完了同步的部分,服务器还没快到这种程度呀。
- 同步中的
ajax.responseText还是空,JSON.parse(ajax.responseText)等同于JSON.parse(null),这便是报错的来源。 - 综上所述,不能直接同步执行
JSON.parse(ajax.responseText),而是告诉JS,“在服务器把JSON发过来之后,再执行JSON.parse(ajax.responseText)”:
let url = "https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw"
let ajax = new XMLHttpRequest()
ajax.open("GET", url)
ajax.send()
ajax.onreadystatechange = function () {
if (ajax.readyState === 4) {
if (ajax.status === 200) {
let obj = JSON.parse(ajax.responseText)
console.log(obj)
}
}
}
//输出:那个JSON解析后的JS对象
jQuery
- jQuery是一个JS的库,功能很强大,BWIKI安装了,就正好利用一下吧。
console.log($)
//输出:ƒ (selector,context){return new jQuery.fn.init(selector,context);}
- 如果你看到了上述结果,说明jQuery是生效的。
console.log($)
//输出:ƒ $() { [native code] }
- 如果你看到了上述结果,说明jQuery没有生效。
let url = "https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw"
$.getJSON(url, function (obj) {
console.log(obj)
})
//输出:那个JSON解析后的JS对象
- 注意:
$.getJSON会自动将JSON解析为JS对象,无需手动使用JSON.parse。 - 因为jQuery无论是获取JSON还是操作DOM元素都实在是太方便了,而且BWIKI也能用,所以本文后续所有的读取JSON都会用jQuery来完成。
查值
- JS将JSON解析后,可以像查JS对象一样查JSON的值。
基本
- 对象:
- 使用英文点
.加键组成对象.键,或者英文方括号[]包裹键的字符串对象["键"],来读取键对应的值:
- 使用英文点
let json = '{"key1":"值1","key2":"值2"}'
let obj = JSON.parse(json)
console.log(obj.key1) //或:console.log(obj["key1"])
//输出:值1
- 数组:
- 使用英文方括号
[]包裹值所在的位置数组[位置],来读取对应位置的值:
- 使用英文方括号
let json = '["零","一","二"]' let arr = JSON.parse(json) console.log(arr[0]) //输出:零
- 注意,数组的第一个元素的位置是0,最后一个元素的位置是长度-1。
- 或许你听过这个段子:程序员数数都是从0开始数的。
- 来点复杂的:
let json = `{
"arr": [
"零",
"一",
{
"inner": "二"
}
]
}`
let obj = JSON.parse(json)
console.log(obj.arr[2].inner)
//输出:二
遍历
- 对象:
- 形如
for (let 键 in 对象) {},让JS访问对象中的所有内容,并执行{}中的动作:
- 形如
let json = `{
"键1": "值1",
"键2": "值2",
"键3": "值3"
}`
let obj = JSON.parse(json)
for (let key in obj) {
console.log(key)
console.log(obj[key]) //请思考一下这里为什么不能用obj.key。
}
//输出:键1
//输出:值1
//输出:键2
//输出:值2
//输出:键3
//输出:值3
- 数组:
- 形如
for (let 位置 = 0; 位置 < 数组.length; 位置++) {},让JS访问数组中的所有内容,并执行{}中的动作:
- 形如
let json = '["零","一","二"]'
let arr = JSON.parse(json)
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
//输出:零
//输出:一
//输出:二
让JSON按照你的想法展示给用户
- 现在,是时候正式阅读一下这个JSON了:https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw 。
- 相信你不难看出,这个JSON描述了一个表格:
- 表格本身拥有
class="wikitable test"; - 表格拥有1个标题行,标题行有4个单元格,内容分别是“序号”、“事件”、“发生时间”、“是否完成”;
- 表格拥有5个内容行,描述了标题行中对应的东西。
- 表格本身拥有
- 就像这样:
| 序号 | 事件 | 发生时间 | 是否完成 |
|---|---|---|---|
| 1 | 起床 | 1660608000000 | true |
| 2 | 吃饭 | 1660608900000 | true |
| 3 | 上车 | 1660609800000 | true |
| 4 | 上班 | 1660613400000 | true |
| 5 | 下班 | 1660645800000 | false |
不要使用WIKI文本
- 通过WIKI文本写出上面这个表格是很简单的
{|class="wikitable test"
|-
!序号||事件||发生时间||是否完成
|-
|1||起床||1660608000000||true
|-
|2||吃饭||1660608900000||true
|-
|3||上车||1660609800000||true
|-
|4||上班||1660613400000||true
|-
|5||下班||1660645800000||false
|}
- 但,JS看不懂WIKI文本,它只能看懂HTML:
<table class="wikitable test"> <tr> <th>序号</th> <th>事件</th> <th>发生时间</th> <th>是否完成 </th> </tr> <tr> <td>1</td> <td>起床</td> <td>1660608000000</td> <td>true </td> </tr> <tr> <td>2</td> <td>吃饭</td> <td>1660608900000</td> <td>true </td> </tr> <tr> <td>3</td> <td>上车</td> <td>1660609800000</td> <td>true </td> </tr> <tr> <td>4</td> <td>上班</td> <td>1660613400000</td> <td>true </td> </tr> <tr> <td>5</td> <td>下班</td> <td>1660645800000</td> <td>false </td> </tr> </table>
DOM操作
获取
- ↓这里放了一个
<div>元素,它拥有id="testDiv1"。
- ↑你现在肯定看不见它,因为它没有任何内容,也没有任何样式:
<div id="testDiv1"></div>
- 看不见不代表不存在,你现在可以通过JS来发现它:
- 再次强调,接下来本文使用的均为jQuery库支持的写法。
let div=$("#testDiv1")
console.log(div)
//输出:jQuery.fn.init [div#testDiv1]
- 尝试往这个
<div>元素中写一句话:
let div=$("#testDiv1")
div.append("你好,世界。")
- 这下就看见它了。
创建
- DOM元素中可以包含另一个DOM元素。
- 先用JS来创建一个DOM元素。
let newDom=$('<span class="newDom">')
console.log(newDom)
//输出:jQuery.fn.init [span.newdom]
- JS创建的DOM也可以变化,试试往里面输入一些文字,然后改变一下它的文字颜色和字号
let newDom=$('<span class="newDom">')
newDom.append("你好,世界")
newDom.css({
"color": "red",
"font-size": "2em"
})
- ↓
- ↑这里放了一个
<div>元素:
<div id="testDiv2"></div>
- 尝试把新的DOM放进上面这个
<div>元素:
let newDom=$('<span class="newDom">')
newDom.append("你好,世界。")
newDom.css({
"color": "red",
"font-size": "2em"
})
let div=$("#testDiv2")
div.append(newDom)
- jQuery还提供一种更便捷的写法:
let newDom=$('<span class="newDom" style="color:red;font-size:2em">你好,世界。</span>')
- 可以直接将表示DOM元素信息的字符串直接变成DOM元素,对创建一些简单的DOM元素会更加方便。
清空
- ↓
你好,世界。
- ↑这里放了一个
<div>元素:
<div id="testDiv3">你好,世界。</div>
- 尝试把上面这个
<div>元素清空:
let div=$("#testDiv3")
div.empty()
- 你看不见它了,但它依然还存在。
实例演示
let url="https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw"
$.getJSON(url, function (obj) {
console.log(obj)
})
//输出:那个JSON解析后的JS对象
- 创建HTML:
let url = "https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw"
$.getJSON(url, function (obj) {
let className = obj.table.class.join(" ")
let html = `<table class="${className}">`
html += `<tr>`
for (let i = 0; i < obj.headLine.length; i++) {
let headLineCell = obj.headLine[i]
html += `<th>${headLineCell}</th>`
}
html += `</tr>`
for (let i = 0; i < obj.lines.length; i++) {
let line = obj.lines[i]
html += `<tr>`
html += `<td>${line[0]}</td>`
html += `<td>${line[1]}</td>`
html += `<td>${line[2]}</td>`
html += `<td>${line[3]}</td>`
html += `</tr>`
}
html += `</table>`
console.log(html)
})
//输出:<table class="wikitable test"><tr><th>序号</th><th>事件</th><th>发生时间</th><th>是否完成</th></tr><tr><td>1</td><td>起床</td><td>1660608000000</td><td>true</td></tr><tr><td>2</td><td>吃饭</td><td>1660608900000</td><td>true</td></tr><tr><td>3</td><td>上车</td><td>1660609800000</td><td>true</td></tr><tr><td>4</td><td>上班</td><td>1660613400000</td><td>true</td></tr><tr><td>5</td><td>下班</td><td>1660645800000</td><td>false</td></tr></table>
- HTML对缩进也不敏感。
- ↓
- ↑这里放了一个
<div>元素:
<div id="tableDiv1"></div>
- 尝试把这段HTML放进上面这个
<div>元素:
let url = "https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw"
$.getJSON(url, function (obj) {
console.log(obj)
let className = obj.table.class.join(" ")
let html = `<table class="${className}">`
html += `<tr>`
for (let i = 0; i < obj.headLine.length; i++) {
let headLineCell = obj.headLine[i]
html += `<th>${headLineCell}</th>`
}
html += `</tr>`
for (let i = 0; i < obj.lines.length; i++) {
let line = obj.lines[i]
html += `<tr>`
html += `<td>${line[0]}</td>`
html += `<td>${line[1]}</td>`
html += `<td>${line[2]}</td>`
html += `<td>${line[3]}</td>`
html += `</tr>`
}
html += `</table>`
let div = $("#tableDiv1")
div.append(html)
})
- ↓
- ↑这里放了一个
<div>元素:
<div id="tableDiv2"></div>
- 你可能会希望把“发生时间”这一列换成“YYYY.MM.DD hh:mm:ss”这样的格式,还希望把“是否完成”这一列换成“是”或“否”:
let url = "https://wiki.biligame.com/tools/index.php?title=MediaWiki:JSONcourse.json&action=raw"
$.getJSON(url, function (obj) {
console.log(obj)
let className = obj.table.class.join(" ")
let html = `<table class="${className}">`
html += `<tr>`
for (let i = 0; i < obj.headLine.length; i++) {
let headLineCell = obj.headLine[i]
html += `<th>${headLineCell}</th>`
}
html += `</tr>`
for (let i = 0; i < obj.lines.length; i++) {
let line = obj.lines[i]
html += `<tr>`
html += `<td>${line[0]}</td>`
html += `<td>${line[1]}</td>`
let time = new Date(line[2])
let YYYY = time.getFullYear()
let MM = (time.getMonth() + 1 + "").padStart(2, "0")
let DD = (time.getDate() + "").padStart(2, "0")
let hh = (time.getHours() + "").padStart(2, "0")
let mm = (time.getMinutes() + "").padStart(2, "0")
let ss = (time.getSeconds() + "").padStart(2, "0")
let timeStr = `${YYYY}.${MM}.${DD} ${hh}:${mm}:${ss}`
html += `<td>${timeStr}</td>`
let isDo
if (line[3]) {
isDo = "是"
} else {
isDo = "否"
}
html += `<td>${isDo}</td>`
html += `</tr>`
}
html += `</table>`
let div = $("#tableDiv2")
div.empty()
div.append(html)
})

沪公网安备 31011002002714 号