← 返回工具首页

JSON解析与序列化完全指南:从原理到实战,让数据流动自如

凌晨两点,你盯着控制台里那个红得刺眼的报错:

SyntaxError: Unexpected token < in JSON at position 0

又来了。接口返回的不是JSON,是一段HTML错误页。你习以为常地复制粘贴,祈祷这次能跑通。

这就是大多数开发者和JSON的关系——每天用,但从来没真正搞懂过它。别担心,这篇文章让你从「会用」升级到「用得明白」。

一、JSON是什么?为什么开发者离不开它

JSON(JavaScript Object Notation)是一种轻量级数据交换格式。它不是JavaScript的专属,而是几乎所有语言都能生成和解析的通用格式。你调API、存配置、做微服务通信——JSON无处不在。

它的核心优势:

简单说:JSON就是程序员的事实标准。搞懂它,你的效率会翻倍。

二、解析(Parsing):把字符串变成对象

JavaScript:JSON.parse()

最常见的场景:拿到一段JSON字符串,解析成JavaScript对象。

const jsonStr = '{"name": "Alice", "age": 25, "skills": ["Python", "Go"]}';
const obj = JSON.parse(jsonStr);
console.log(obj.name); // "Alice"
console.log(obj.skills[0]); // "Python"

看起来简单,但有三个坑你必须知道:

坑1:严格模式,不允许尾部逗号

// 这会报错
JSON.parse('{"name": "Bob",}'); // SyntaxError: Unexpected token }

// 正确写法
JSON.parse('{"name": "Bob"}');

坑2:属性名必须用双引号

// 单引号 → 报错
JSON.parse("{'name': 'Carol'}"); // SyntaxError: Unexpected token '

// 正确
JSON.parse('{"name": "Carol"}');

坑3:undefined和函数会被忽略

const obj = {
  name: "Dave",
  age: undefined,   // 被忽略
  greet: function() { return "hi"; }, // 被忽略
  active: true
};
const jsonStr = JSON.stringify(obj);
console.log(jsonStr); // {"name":"Dave","active":true}
console.log(JSON.parse(jsonStr).age); // undefined

Python:json.loads()

Python中解析JSON用的是json模块的loads()函数(load string)。

import json

json_str = '{"name": "Alice", "age": 25, "skills": ["Python", "Go"]}'
obj = json.loads(json_str)
print(obj["name"])  # Alice
print(obj["skills"][0])  # Python

Python的坑主要在于类型映射:JSON的true/false变成Python的True/Falsenull变成None。如果你习惯用None做判断,别忘了这一层转换。

三、序列化(Serialization):把对象变成字符串

JavaScript:JSON.stringify()

序列化是将对象转换为JSON字符串的过程。

const obj = { name: "Eve", score: 98.5, passed: true };
const jsonStr = JSON.stringify(obj);
console.log(jsonStr);
// {"name":"Eve","score":98.5,"passed":true}

JSON.stringify()还支持两个额外的参数:

第二个参数:过滤器和格式化

const obj = { name: "Frank", age: 30, password: "secret123" };

// 只保留指定字段
const filtered = JSON.stringify(obj, ["name", "age"]);
console.log(filtered); // {"name":"Frank","age":30}

// 用函数自定义处理
const custom = JSON.stringify(obj, (key, value) => {
  if (key === "password") return undefined; // 排除密码字段
  return value;
});
console.log(custom); // {"name":"Frank","age":30}

第三个参数:缩进美化

const obj = { name: "Grace", city: "Beijing" };

// 用空格缩进(2个空格)
console.log(JSON.stringify(obj, null, 2));
// {
//   "name": "Grace",
//   "city": "Beijing"
// }

// 用制表符缩进
console.log(JSON.stringify(obj, null, "\t"));
// {
//     "name": "Grace",
//     "city": "Beijing"
// }

注意:格式化输出只适合调试和日志,生产环境传输应使用无缩进的最小化格式,否则徒增网络开销。

Python:json.dumps()

import json

obj = {"name": "Grace", "city": "Beijing", "score": 98.5}
json_str = json.dumps(obj)
print(json_str)  # {"name": "Grace", "city": "Beijing", "score": 98.5}

# 美化输出(indent参数)
print(json.dumps(obj, indent=2, ensure_ascii=False))
# {
#   "name": "Grace",
#   "city": "Beijing",
#   "score": 98.5
# }

# 排除某个字段
obj.pop("score", None)
print(json.dumps(obj))  # {"name": "Grace", "city": "Beijing"}

ensure_ascii=False在处理中文时是必须的,否则中文会被转义为\u4e2d...的形式,可读性大幅下降。

四、实战技巧:处理复杂场景

1. 深拷贝:比Object.assign更安全

// Object.assign是浅拷贝,嵌套对象会共享引用
const original = { user: { name: "Henry", scores: [90, 85] } };
const shallow = Object.assign({}, original);
shallow.user.name = "Hank";
console.log(original.user.name); // "Hank" — 原对象被改了!

// JSON.stringify + JSON.parse 实现深拷贝
const deep = JSON.parse(JSON.stringify(original));
deep.user.name = "Hank";
console.log(original.user.name); // "Henry" — 安全

注意:这种方法无法拷贝函数、undefinedSymbol等特殊值。如果你的对象包含这些类型,需要用专门的深拷贝库(如lodash的cloneDeep)。

2. 处理日期对象

// 日期对象序列化后变成字符串,反序列化后还是字符串
const event = { title: "Conference", date: new Date("2026-05-10") };
const str = JSON.stringify(event);
console.log(str); // {"title":"Conference","date":"2026-05-10T00:00:00.000Z"}

const parsed = JSON.parse(str);
console.log(parsed.date); // "2026-05-10T00:00:00.000Z" — 是字符串,不是Date对象

// 如需还原为Date对象,自定义reviver函数
const restored = JSON.parse(str, (key, value) => {
  if (key === "date") return new Date(value);
  return value;
});
console.log(restored.date instanceof Date); // true

3. 循环引用的处理

// 直接序列化包含循环引用的对象会报错
const obj = { name: "Iris" };
obj.self = obj;
try {
  JSON.stringify(obj);
} catch (e) {
  console.log(e.message); // "Converting circular structure to JSON"
}

// 解决方案:用 replacer 过滤或使用库
const safeObj = JSON.stringify(obj, (key, value) => {
  if (value === obj) return "[Circular]";
  return value;
});
console.log(safeObj); // {"name":"Iris","self":"[Circular]"}

4. 大数字精度丢失问题

// JavaScript中Number类型的安全整数范围:-2^53+1 到 2^53-1
// 超过这个范围的数字会丢失精度
const bigNum = { id: 9007199254740993 }; // 2^53+1
console.log(JSON.parse(JSON.stringify(bigNum)).id); // 9007199254740992 — 精度丢失!

// 解决方案:用字符串传递大数字,或使用专门的bigint库

五、常见错误与解决方案

错误信息 原因 解决方式
Unexpected token in JSON 字符串包含非法字符或格式错误 检查JSON有效性,用工具格式化验证
Unexpected end of JSON input 字符串被截断,或为空 检查接口响应是否完整,body是否为空
Expected ',' or '}' 少了逗号或多了逗号 逐行检查JSON结构
Unexpected character in JSON 属性名用了单引号或未加引号 属性名必须用双引号包裹
Converting circular structure to JSON 对象存在循环引用 用replacer过滤或移除循环引用
BOM头导致的解析错误 UTF-8文件带BOM头 保存文件时选择「UTF-8 无BOM」格式
中文字符变成Unicode转义 未设置ensure_ascii=False(Python) json.dumps(obj, ensure_ascii=False)

六、推荐工具:用在线JSON格式化器省时间

手动处理JSON太累了?善用工具能让你事半功倍。

如果你需要一个能实时校验、格式化、美化的JSON工具,我常用 CloverTools JSON Formatter。它能帮你:

地址:https://clovertools.cn/tools/json/formatter.html

写代码时我习惯浏览器开一个标签页,接口返回的JSON直接丢进去格式化,省去本地跑脚本的麻烦。

七、总结

JSON的解析和序列化看似基础,但细节坑不少:

把这些细节变成肌肉记忆,下次遇到JSON报错时,你就不用再靠运气了。

工具地址再放一次:https://clovertools.cn/tools/json/formatter.html — 用起来,效率翻倍。

💡 遇到同类问题?用工具快速解决

试试这些配套工具,无需注册,打开即用

JSON 格式化

常见问题

Q: 如何使用 json怎么解析序列化 相关工具?
A: 这类工具一般有明确的输入框和输出框,按提示输入内容,点击对应按钮即可得到结果。建议先用简单示例测试功能是否正常,再处理实际数据。
Q: json怎么解析序列化 适合在什么场景使用?
A: 根据具体工具类型决定。格式转换工具适合处理第三方数据,编码工具适合加密传输,压缩工具适合文件上传前处理。多积累工具使用经验,遇到问题时能快速判断用哪个工具解决。
Q: 有没有更好的替代工具?
A: 不同工具有不同侧重,重点是理解原理。可以同时安装多个类似工具,实际使用中对比效果,选择最顺手的一个。随着使用经验增加,你也能判断工具的好坏。