JSON 就是前后端传数据的标准格式,本质是字符串,但长得像 JS 对象。
核心两个:
1. JSON.stringify(obj)——对象转字符串
2. JSON.parse(str)——字符串转对象
坑:JSON 键名必须双引号、不能有函数和 undefined、JSON 不是对象(是字符串)。
但要注意:JSON 本质上是一段纯字符串,不是 JS 对象。它长得像 JS 对象,但它是"书面文字",JS 看不懂,得先用 JSON.parse 翻译成 JS 对象才能用。反过来,你要把数据传给后端,也得用 JSON.stringify 把 JS 对象翻译成 JSON 字符串。这一进一出,就是这节课要掌握的全部。
打个比方:英语是全世界通用的沟通语言,法国人、日本人、中国人都用英语交流。JSON 就是编程世界里的"英语"——不管后端用什么语言写,前端用 JS 读,大家都用 JSON 来交换数据。
如果没有 JSON,Java 后端给你送一个它自己格式的数据,你的 JS 根本不认识,就像法国人给你递了一份法语菜单,你看不懂。有了 JSON,大家都用"普通话"传数据,谁都能解析。
// 类比:英语 = 全球人类通用语言 // JSON = 所有编程语言通用的"数据语言" // 后端 Java/PHP/Python 和前端 JS 之间传数据,统一用 JSON // 因为 JSON 是纯文本,谁都能读,不挑编程语言 // ★ 关键认知:JSON 本质是纯字符串,不是 JS 对象! // 它只是"长得像" JS 对象,但它是一段文本。 // 就像一封写在纸上的信,纸是纸,字是字, // 你得先"读信"(JSON.parse)才能知道信里写了什么。
如果你把 JSON 当成 JS 对象直接访问 .name,就会报错——因为它是字符串,字符串没有 .name 属性。因为 JSON 只是"长得像"对象的一段文字,必须先 JSON.parse 才变成真对象。
JSON 有两种最常用的"长相":一种是对象型(像字典,有键有值),一种是数组型(像清单,一排数据)。
// 1. 对象型 JSON(键值对)—— 描述"一个东西的各项属性"
// 像字典:"名字"是"张三","年龄"是18
// ← 这就是对象型:像字典,有键有值
{ "name": "张三", "age": 18, "gender": "男" }
// 2. 数组型 JSON(批量数据)—— 描述"一排东西"
// 像购物清单:苹果、香蕉、橙子
// ← 这就是数组型:像清单,一排排好的数据
["苹果", "香蕉", "橙子"]
// 数组里也能装对象(最常见!接口返回的列表数据基本都长这样)
// [ {"id":1,"name":"商品A"}, {"id":2,"name":"商品B"} ]
JSON 有自己严格的"语法规矩",比 JS 严格多了。下面六条每一条都是新手常犯的错,记住:
// 规则1:JSON 本质是纯字符串,不属于 JS 独有语法
// (它只是刚好和 JS 对象长得像而已)
// 规则2:业务开发最常用对象型、数组型两种结构
// (标准语法上顶层也能写纯字符串、数字、布尔、null,但项目里基本不用)
// 规则3:所有键名必须用双引号包裹!
// "name" 正确
// 'name' 单引号,非法
// name 不加引号,非法
// 规则4:值允许写——字符串、数字、布尔(true/false)、null
// 值禁止写——function(函数)、undefined、NaN
// 因为 JSON 是纯数据,不能放代码
// 规则5:数组/对象末尾不能多一个逗号!
// {"a":1, "b":2} 正确
// {"a":1, "b":2,} 末尾多逗号,解析直接报错
// 规则6:JSON 文件后缀是 .json
// 文件里只能写纯 JSON 数据,
// 不能写 JS 代码、不能写注释(
// 这种在 .json 里是非法的!)
如果你写 {'name':'张三'}(用了单引号),JSON.parse 会直接报错——因为 JSON 规定键名必须双引号。如果你在末尾多写了个逗号 {"a":1,},也会报错——因为 JSON 不允许尾随逗号。这两条是新手 80% 报错的来源。
前面说了,JSON 是字符串,JS 对象是对象,两者之间要"翻译"。JS 自带了一对翻译机:
// ===== 翻译机一:JSON.stringify =====
// 作用:把 JS 对象 → JSON 字符串
// 什么时候用:要把数据存进 localStorage、要传给后端时
// 这是一个 JS 对象
let user = { name: "张三", age: 18 };
// 翻译:对象 → 字符串
let jsonStr = JSON.stringify(user);
// 打印:{"name":"张三","age":18}
console.log(jsonStr);
// ★ 注意:打印出来的是字符串,外面没有单引号包裹是因为
// console.log 自动去掉了外层引号
// ===== 翻译机二:JSON.parse =====
// 作用:把 JSON 字符串 → JS 对象
// 什么时候用:收到后端返回的数据、从 localStorage 读数据时
// 翻译:字符串 → 对象
let jsObj = JSON.parse(jsonStr);
// 打印:张三(现在能 .name 了!)
console.log(jsObj.name);
// ===== 单独写一段 JSON 字符串时,外面要套单引号 =====
// 因为双引号在 JS 里会提前结束字符串,所以外层用单引号
// 外层单引号,内层双引号
let str = '{"fruit":"苹果","price":9.9}';
// 解析成对象
let res = JSON.parse(str);
// 打印:苹果
console.log(res.fruit);
如果你把一段格式不对的 JSON 传给 JSON.parse,浏览器会直接抛 SyntaxError 红色报错,整个程序卡住。因为 parse 遇到不认识的格式会崩溃。所以实际项目里一定要用 try/catch 包起来,像下面这样:
try {
// 尝试解析
let obj = JSON.parse(可能有问题的字符串);
} catch (e) {
// 出错就走这里,不崩溃
console.log("JSON 格式不对:" + e.message);
}
// 场景1:前后端接口数据交互(最常用!)
// 后端返回的数据默认就是 JSON 格式
// 你 xhr.responseText 拿到的就是 JSON 字符串
// 场景2:本地存储 localStorage / sessionStorage
// 这俩只能存字符串!不能直接存对象
// 存之前 stringify,取出来之后 parse
// 存
localStorage.setItem("user", JSON.stringify(user));
// 取
let back = JSON.parse(localStorage.getItem("user"));
// 场景3:配置文件、项目静态数据
// 比如配置文件 config.json,只放纯数据
可能在什么地方用:
1. 后端接口返回数据时,你拿到的 xhr.responseText 就是 JSON 字符串,必须 JSON.parse 才能用
2. 往 localStorage 存对象/数组时,必须先 JSON.stringify,因为它只认字符串
3. 写 config.json 配置文件时,整个文件就是纯 JSON。
常见的问题:
1. 忘记 JSON.parse 就直接访问 data.name,结果打印出来是 undefined——因为它还是字符串
2. 拼 JSON 时键名写了单引号或没加引号,JSON.parse 直接报 SyntaxError
3. 末尾多写了逗号 {"a":1,},解析崩溃
4. 把 undefined 或函数当值塞进 JSON,JSON.stringify 会直接丢掉这个字段。
解决思路:
1. 报错时先看 Console 红字——SyntaxError: Unexpected token 就是 JSON 格式不对,回头查双引号和逗号
2. 解析前用 try/catch 包起来,出错不崩页面
3. 不确定时,把字符串贴到浏览器 Console 手动跑一次 JSON.parse(粘贴的内容),立刻知道哪错了。
练习一:JSON 格式校验新建 demo1.html,判断下面哪些是合法 JSON?在注释里写出判断依据。
// 1. {"name": "张三", "age": 18} → 合法吗?为什么?
// 2. {'name': '张三', 'age': 18} → 合法吗?为什么?
// 3. {name: "张三", age: 18} → 合法吗?为什么?
// 4. {"name": "张三", "age": 18,} → 合法吗?为什么?
// 5. ["苹果", "香蕉", "橙子"] → 合法吗?为什么?
// ⑥ "hello" → 合法吗?为什么?
// ⑦ {"name": "张三", "age": undefined} → 合法吗?为什么?
// 再动手转一转:
// ⑧ 把 JS 对象 { name:"李四", age:25, hobbies:["读书","跑步"] }
// 用 JSON.stringify 转成字符串,打印结果
// ⑨ 把 JSON 字符串 '{"name":"王五","age":30,"address":{"city":"北京"}}'
// 用 JSON.parse 转成对象,打印 data.address.city
提示:对照上面六条规范一条一条查。2. 用了单引号、3. 没引号、4. 末尾多逗号、⑦值是 undefined——这几个是坑。
| API | 作用 | 参数 | 返回值 | 代码示例 |
|---|---|---|---|---|
| JSON.parse(str) | 把 JSON 字符串翻译成 JS 对象 | 入参:JSON 字符串 | 返回:JS 对象;格式错会抛错 | let obj = JSON.parse('{"name":"张三"}'); |
| JSON.stringify(obj) | 把 JS 对象打包成 JSON 字符串 | 入参:JS 对象 | 返回:JSON 字符串 | let str = JSON.stringify(obj); |
| localStorage.setItem(k,v) | 把数据存到浏览器本地 | 入参:键名、字符串值 | 返回:无 | localStorage.setItem("token", "abc123"); |
| localStorage.getItem(k) | 从浏览器本地取数据 | 入参:键名 | 返回:字符串;没有就 null | let t = localStorage.getItem("token"); |