Python 的 json:别再用字符串拼接造 JSON

举报
yd_268445051 发表于 2026/11/14 10:01:32 2026/11/14
【摘要】 Python 的 json:别再用字符串拼接造 JSON写 Python 时,跟别的服务打交道几乎绕不开 JSON:接口返回的是它,配置文件是它,日志里存的也是它。顺手写法是用字符串拼接来造一段 JSON——"{\"name\": \"" + name + "\"}",跑起来好像没问题,可一旦字段里出现引号、换行或者中文,拼出来的东西就很容易不是合法的 JSON:引号没转义、逗号多一个少一...

Python 的 json:别再用字符串拼接造 JSON

写 Python 时,跟别的服务打交道几乎绕不开 JSON:接口返回的是它,配置文件是它,日志里存的也是它。顺手写法是用字符串拼接来造一段 JSON——"{\"name\": \"" + name + "\"}",跑起来好像没问题,可一旦字段里出现引号、换行或者中文,拼出来的东西就很容易不是合法的 JSON:引号没转义、逗号多一个少一个,对方一解析就报错。JSON 值得交给一个专门的模块来管,那就是标准库的 json。

先看最基本的往返:把 Python 对象转成 JSON 字符串,再转回来。

import json

data = {"name": "华为云", "points": 2800, "tags": ["签到", "文章"]}
text = json.dumps(data)
json.loads(text) == data  # True

dumps 负责序列化,loads 负责反序列化,两个方向各用一个函数,规则都在模块内部处理好:字符串里的引号会被自动转义,嵌套的字典和列表也能原样还原。自己拼字符串时最容易漏的,恰恰就是这些转义细节。

第二个顺手的是输出给人看的格式。默认的 dumps 会把中文转成 \u 形式,还把所有内容挤在一行,调试时很难读:

import json

data = {"name": "华为云", "points": 2800, "tags": ["签到", "文章"]}
json.dumps(data, ensure_ascii=False, indent=2)

ensure_ascii=False 让中文直接以中文输出,不再转成 \uXXXX;indent=2 按两格缩进换行,结构一目了然。这两个参数只影响输出的样子,不影响内容,写日志、写配置文件时加上它们,之后排查问题会轻松很多。

第三个是自定义类型。datetime、Decimal 这类对象 json 默认不认识,直接传进去会抛 TypeError:

import json
from datetime import datetime

def default(obj):
    if isinstance(obj, datetime):
        return obj.strftime("%Y-%m-%d %H:%M:%S")
    raise TypeError(f"不支持的类型:{type(obj)}")

json.dumps({"at": datetime(2026, 11, 14, 9, 44)}, default=default)

default 参数是一个兜底函数:遇到模块不认识的对象就调它,返回一个能序列化的值。把转换规则集中写在这里,比在每个调用处先把时间手动转成字符串要干净,也不会漏掉某个字段。

最后说解析那头的坑。外部传来的 JSON 不一定合法,loads 遇到坏格式会抛 JSONDecodeError,不处理就会让整个程序崩掉:

import json

try:
    json.loads('{"points": 2800,}')
except json.JSONDecodeError as e:
    print(f"解析失败:{e}")

注意那串文本里 2800 后面多了一个逗号——这在 Python 字典里是合法的,在 JSON 里不合法。JSONDecodeError 会告诉你错在哪一行、哪一列,捕获它并记下原始文本,比让异常一路冒泡要好查得多。另外,loads 只接受 str、bytes 或 bytearray,传一个已经是字典的对象进去同样会报错,调用前先确认拿到的是文本。

字符串拼接不是不能造 JSON,只是把本该由解析器保证的正确性,交给了人手去保证——引号、转义、逗号、编码,每一处都可能漏。用 json 模块,这些事就都有了统一的答案,写的人少操心,读的人也少猜。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。