查看: 356|回复: 0

Python字符串与JSON互转:loads/dumps及文件读写避坑指

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在Python开发中,字符串与JSON数据之间的转换是高频操作,尤其是接口调用、配置文件解析、数据持久化等场景。许多初学者在转换时会遇到引号格式错误、直接对文件对象调用loads()导致TypeError等问题。本文基于实际命令和报错现象,梳理str与json互转的四个核心方法:json.load()、json.loads()、json.dump()、json.dumps(),并指出典型的错误原因与排查路径。

一、json.load():从文件对象读取JSON并转为Python对象
json.load(fp)的作用是将一个文件对象(file object)反序列化为Python对象,通常结果是dict。要注意的是,文件名不一定要以.json结尾,但文件内容必须是合法的JSON格式。该方法接受支持.read()的文本文件或二进制文件。

常见的两种写法效果相同:
  1. import json
  2. # 写法一:使用with自动关闭文件
  3. with open('aa.json', 'r') as data_file:
  4.     f = json.load(data_file)
  5. print(type(f))  # <class 'dict'>
  6. print(f)        # {'today': '0326', 'id': '11'}
  7. # 写法二:手动open与close
  8. file = open('aa.json')
  9. data = json.load(file)
  10. file.close()
  11. print(data)
复制代码
推荐使用with open(),因为即使解析过程中出现问题,也能自动调用close()释放文件句柄。

如果aa.json中的内容不是合法JSON,会抛出JSONDecodeError,并提示具体位置:
  1. raise JSONDecodeError("Expecting value", s, err.value) from None
  2. json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)
复制代码
这类报错常见于文件内容为空、多行普通文本、或JSON结尾多了逗号。排查时应先用文本编辑器打开文件,确认内容是否为标准的JSON格式。

二、json.loads():将JSON字符串转为Python对象
json.loads(s)用于将包含JSON文档的str、bytes或bytearray反序列化为Python对象。它的主要应用场景是把从接口获取的字符串数据转成dict。需要注意:loads只能处理字符串,不能直接解析文件对象,否则会报错。

正确用法:
  1. import json
  2. a = '{"today": "0326", "id": "11"}'
  3. b = json.loads(a)
  4. print(type(b))  # <class 'dict'>
  5. print(b)        # {'today': '0326', 'id': '11'}
复制代码

如果字符串中的键或值用了单引号,比如:
  1. a = "{'today': '0326', 'id': '11'}"
  2. b = json.loads(a)
复制代码
Python会报出:
  1. json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
复制代码
原因在于JSON标准要求键名和字符串值必须使用双引号。解决办法是确保传入loads的字符串内部使用双引号,外层可以用单引号包裹,例如:
  1. a = '{"today": "0326", "id": "11"}'
复制代码
这是最常见的str与json互转错误之一,排查思路很简单:先打印待转换的原始字符串,检查引号样式。

如果把文件对象直接传给loads,会抛出TypeError:
  1. TypeError: the JSON object must be str, bytes or bytearray, not TextIOWrapper
复制代码
看到TextIOWrapper即可知道传入的是文件句柄而非字符串。这时应改用json.load(file_object)来读取文件,或先通过file.read()获得字符串再调用loads。

三、json.dump():把Python对象写入文件
json.dump(obj, fp)将Python对象序列化为JSON格式的流,并写入支持.write()的文件对象。该函数没有返回值,直接对调用结果打印会得到None。
  1. import json
  2. a = {"today": "0326", "id": "22222"}
  3. with open("bb.json", 'w') as f:
  4.     json.dump(a, f)
  5. print(json.dump(a, f))  # 错误示例:此时f已关闭,且dump无返回值
复制代码
正确验证写入结果的方式是重新读取文件内容:
  1. with open("bb.json", 'r') as f:
  2.     print(f.read())
  3. # 输出:{"today": "0326", "id": "22222"}
复制代码
如果在with块内打印json.dump(a, f),会得到None,即dump本身没有返回数据。不要试图将dump的结果赋值给变量,它只负责把数据写入文件。

四、json.dumps():将Python对象转为JSON字符串
dumps与dump只差一个字母,但用途完全不同。dumps把Python对象(dict、list等)序列化为JSON字符串,返回值类型为str。
  1. import json
  2. a = {"today": "0326", "id": "22222"}
  3. # 如果是列表也可以
  4. # a = [{"today": "0326", "id": "22222"}]
  5. json_str = json.dumps(a)
  6. print(json_str)        # {"today": "0326", "id": "22222"}
  7. print(type(json_str))  # <class 'str'>
复制代码
dumps常用于需要把dict转成字符串后写入文件、日志或作为请求体发送。注意:JSON的键/值对中键永远是字符串类型。当dict被序列化为JSON后,其键会被强制转为字符串,因此再通过loads转回dict时,如果原dict包含非字符串键(如数字、元组),结果可能与原始数据不一致。也就是说,loads(dumps(x))不一定等于x,尤其是x存在非字符串键时。

例如:
  1. data = {1: 'a', 2: 'b'}
  2. s = json.dumps(data)
  3. print(s)            # {"1": "a", "2": "b"}
  4. back = json.loads(s)
  5. print(back)         # {'1': 'a', '2': 'b'},键变成字符串了
复制代码
这是一个容易被忽略的兼容性细节。在需要保留键类型的业务中,建议先将键转为字符串,或在反序列化后做类型校正。

五、四个方法对比与适用场景
json.load():文件对象 -> Python dict,常用于解析JSON配置文件、接口响应体文件。
json.loads():JSON字符串 -> Python dict,常用于处理requests等库返回的文本型JSON。
json.dump():Python对象 -> 写入文件对象,无返回值,常用于把数据保存到本地JSON文件。
json.dumps():Python对象 -> JSON字符串,常用于生成日志、组装接口请求体、进行序列化传输。

使用建议:
- 文件内容解析统一用load;字符串解析统一用loads,不要混用。
- 编码报错时,先检查JSON内容是否为UTF-8,且字符串引号是否为半角双引号。
- 写入文件时注意用'w'模式,若文件已存在会覆盖;需要追加时可改用'a'。
- dumps的indent参数可以在格式化输出时使用,比如json.dumps(data, indent=2, ensure_ascii=False),便于阅读中文内容。

掌握这四个方法的区别,能有效避免str与json转换过程中的常见异常,也能让本地数据读写和接口数据解析代码更加稳定、可维护。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-6 14:40 , Processed in 0.020615 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部