这一章讲的东西,你天天都在用:你的 Worker、Surge 脚本、各种接口,传来传去的数据几乎都是 JSON。学完这一章,你就能自己把数据「打包成文字发出去、收到文字拆开来用」。
一句话目标:会用 JSON.stringify 和 JSON.parse 在「对象」和「文字」之间互相转换;知道 JSON 的严格规矩;知道 parse 遇到坏数据会直接抛错这个坑,解析之前要防着它。
{ a: 1 },你能用 .a 取里面的值。'{"a":1}'。它只是一段文字,不能直接用 .a 取值,必须先变回对象。JSON 是全世界接口传数据的统一格式。不管对方是什么语言写的程序,大家都按这个格式写文字,就都能看懂。
它长得和 JS 对象很像,但规矩比 JS 严得多。写错一点,对方就解析不了:
记住一句:JSON 是「写给机器看的文字」,不是代码,所以它不许随便。
JSON.stringify什么时候用:要把数据发出去、存起来之前。把对象打包成文字。
const text = JSON.stringify({ a: 1, b: [1, 2] });
console.log(text);
// 结果是文字:'{"a":1,"b":[1,2]}'
// 注意:键 a、b 都被自动加上了双引号
JSON.parse什么时候用:收到数据后的第一件事。把文字拆回对象,才能取里面的字段。
const obj = JSON.parse(text);
console.log(obj.b[0]);
// text 是上面那段文字,parse 之后变回对象
// b 是 [1, 2],取第 0 个,结果是 1
JSON.stringify(obj, null, 2)默认打包出来的文字是挤成一行的,自己看很难受。加上 null, 2 两个参数,就会换行 + 缩进 2 格,调试看数据时特别好用。
const pretty = JSON.stringify(obj, null, 2);
console.log(pretty);
// 输出会变成一行一行、带缩进的样子:
// {
// "a": 1,
// "b": [
// 1,
// 2
// ]
// }
JSON.parse 遇到格式不对的字符串,不会返回个错误提示,而是直接抛错——程序到这一行就崩了,后面的代码全不执行。
所以规矩是:解析外部来的数据(接口返回、响应体这种你控制不了的东西),必须把 parse 包在 try/catch 里面,崩了也能接住、走备用处理:
try {
const obj = JSON.parse(text); // 解析外部数据
console.log("解析成功", obj);
} catch (e) {
console.log("解析失败:" + e.message); // 崩了在这里接住
}
还有一条:响应体是不是 JSON 没把握时,先判断再 parse。比如先看看开头是不是 {,或者接口有没有说明返回类型,别上来就 parse 一段网页文字。
下面 4 段代码都能真的运行:点「运行」,就在这页里执行,结果显示在代码下面。建议按顺序一个一个点。
运行 JSON.stringify({a: 1, b: [1, 2]}),注意输出里 a、b 都变成了 "a"、"b"。
const obj = { a: 1, b: [1, 2] };
const text = JSON.stringify(obj);
console.log(text);
console.log("类型是:" + typeof text);
运行 JSON.parse('{"a":1}') 再取 .a,看拿到的 1 是数字,不是文字。
const text = '{"a":1}';
const obj = JSON.parse(text);
console.log(obj.a);
console.log("类型是:" + typeof obj.a);
"不是 JSON" 根本不是 JSON 格式,parse 它必然抛错。用 try/catch 包住,错误会被接住,程序不会崩。
try {
JSON.parse("不是 JSON");
console.log("解析成功");
} catch (e) {
console.log("解析失败:" + e.message);
}
同一份数据,加上 null, 2 后换行缩进,对比一下第 1 个练习里挤成一行的样子。
const obj = { name: "小明", age: 18, tags: ["学习", "JS"] };
const pretty = JSON.stringify(obj, null, 2);
console.log(pretty);
Surge 脚本里拿到的 $response.body 是一段 JSON 文字,不能直接改字段。固定套路就三步:
JSON.parse 把 body 拆成对象;JSON.stringify 打包回文字,交还给 Surge。let obj = JSON.parse($response.body); // 第 1 步:文字 → 对象
obj.vip = true; // 第 2 步:改字段
$done({ body: JSON.stringify(obj) }); // 第 3 步:对象 → 文字,交回去
少了第 1 步就改不动字段;少了第 3 步,交回去的就不是文字,Surge 不认。
Worker 的 Response(响应)装的也是文字。所以把对象 stringify 之后塞进去,对方收到的就是标准 JSON:
return new Response(JSON.stringify({ ok: true }), {
headers: { "content-type": "application/json" }
});
// 对方收到的是文字:'{"ok":true}'
// 对方再用 JSON.parse 就能取到 ok 这个字段
KV 里只能存字符串,存不进对象。所以你的 tg-bot、MiSub 这些用到 KV 的地方,全都是这个套路:
// 存:对象先 stringify 成文字,才能放进 KV
await KV.put("user", JSON.stringify({ count: 3 }));
// 读:拿出来的是文字,先 parse 回对象再用
const text = await KV.get("user");
const user = JSON.parse(text);
console.log(user.count); // 3
忘了 parse 就直接 text.count,只会得到 undefined(取不到)——这是新手最常踩的坑之一。
发出去、存起来之前用 JSON.stringify 打包成文字;收到数据先用 JSON.parse 拆回对象,拆外部数据时记得用 try/catch 防它抛错。
第八章:异步 —— Promise、async / await、fetch
数据为什么不是马上就到、代码怎么「等」数据回来,下一章讲清楚。
第七章完 · 点过「运行」、做完 5 道题,这一章就算过关了