python处理json数据的核心是使用内置json模块的四个主要函数。1. json.loads()将json字符串解析为python对象,适用于网络请求等场景。2. json.load()直接从文件解析json数据,比先读取文件内容再用loads更高效。3. json.dumps()将python对象序列化为json字符串,支持格式化输出、非ascii字符处理等。4. json.dump()将python对象写入文件,适用于保存配置或用户数据。此外,处理json时需注意jsondecodeerror、keyerror、数据类型不匹配等问题,可通过异常捕获、dict.get()方法、类型转换等方式应对。对于大规模json数据或性能要求较高的场景,可使用ijson进行流式解析,或使用ujson、orjson等高性能库提升处理效率。

Python处理JSON格式数据,核心在于使用其内置的json模块。这个模块提供了一套直观的API,用于实现Python对象与JSON格式字符串之间的相互转换。简单来说,你需要将JSON字符串解析成Python字典或列表,或者将Python字典/列表转换成JSON字符串。

在Python中,处理JSON主要涉及两个方向:解析(Deserialization)和转换(Serialization)。
解析JSON数据(从JSON字符串到Python对象)
立即学习“Python免费学习笔记(深入)”;

当你从文件、网络请求(比如API响应)中获取到JSON格式的文本时,你需要将其解析成Python能够理解和操作的数据结构,通常是字典(dict)或列表(list)。
json.loads(s): 这个函数用于将一个JSON格式的字符串s解析成Python对象。

import json
json_string = '{"name": "张三", "age": 30, "isStudent": false, "courses": ["Math", "Physics"]}'
data = json.loads(json_string)
print(type(data))
print(data['name'])
print(data['courses'][0])
# 很多时候,我们从API拿到的响应就是JSON字符串
api_response_str = '[{"id": 1, "item": "Laptop"}, {"id": 2, "item": "Mouse"}]'
items = json.loads(api_response_str)
print(type(items))
print(items[0]['item'])这里有个小插曲,我个人觉得loads这个名字挺形象的,"load string",从字符串里加载。
json.load(fp): 如果你的JSON数据存储在一个文件中,或者是一个类似文件的对象(file-like object),你可以使用json.load()直接从文件句柄fp中读取并解析。
# 假设有一个名为 'data.json' 的文件
# 内容可能是:{"city": "Beijing", "population": 21000000}
with open('data.json', 'r', encoding='utf-8') as f:
config = json.load(f)
print(config['city'])用load处理文件,省去了先读文件内容再loads的步骤,更高效一些。
转换Python对象到JSON数据(从Python对象到JSON字符串)
当你需要将Python中的数据结构(比如一个字典、一个列表)发送给API,或者保存到文件中时,你需要将它们转换成JSON格式的字符串。
json.dumps(obj): 这个函数用于将Python对象obj序列化(转换)成一个JSON格式的字符串。
my_data = {
"product_id": "ABC123",
"name": "Wireless Keyboard",
"price": 49.99,
"features": ["ergonomic", "bluetooth", "rechargeable"],
"available": True
}
json_output = json.dumps(my_data)
print(type(json_output))
print(json_output)
# 默认输出是紧凑的,不好阅读
# 我们可以通过参数让它“漂亮”一点
pretty_json_output = json.dumps(my_data, indent=4, ensure_ascii=False)
print(pretty_json_output)dumps就是"dump string",把对象倾倒成字符串。indent参数非常实用,能让JSON字符串带上缩进,便于人眼阅读。ensure_ascii=False在处理包含中文等非ASCII字符时特别有用,它会直接输出Unicode字符而不是uXXXX的形式。
json.dump(obj, fp): 如果你想直接将Python对象序列化并写入到一个文件句柄fp中,可以使用json.dump()。
new_user = {
"username": "coder_xiaoming",
"email": "xiaoming@example.com",
"registration_date": "2023-10-26"
}
with open('user_profile.json', 'w', encoding='utf-8') as f:
json.dump(new_user, f, indent=2, ensure_ascii=False)
# 文件 'user_profile.json' 现在包含了格式化的JSON数据这就像是直接把Python对象“倒”进了文件里。
在实际开发中,解析JSON数据并非总是一帆风顺,总会遇到一些让人挠头的问题。
一个很常见的场景是数据格式不规范。比如,你期望一个字段是整数,结果它是个字符串;或者更糟糕的是,JSON字符串本身就不符合规范。
1. json.JSONDecodeError:JSON格式错误
这是最常见的错误。当json.loads()或json.load()尝试解析一个不是有效JSON格式的字符串时,就会抛出这个异常。
原因:
应对策略:
invalid_json = "{'name': 'Bob'}" # 错误:单引号
another_invalid = '{"a": 1,}' # 错误:末尾逗号
try:
data = json.loads(invalid_json)
except json.JSONDecodeError as e:
print(f"解析错误:{e}")
print("请检查JSON字符串是否符合规范,例如键和字符串值必须使用双引号。")
try:
data = json.loads(another_invalid)
except json.JSONDecodeError as e:
print(f"解析错误:{e}")
print("请检查JSON字符串中是否有不合法的末尾逗号。")在实际应用中,尤其是在处理外部来源(如API)的数据时,务必使用try-except块来捕获JSONDecodeError,这样程序才不会崩溃,可以优雅地处理错误。
2. 键不存在(KeyError)
当你解析完JSON数据得到一个Python字典后,如果尝试访问一个不存在的键,就会触发KeyError。
原因:数据提供方可能没有总是包含某个字段,或者字段名拼写错误。
本文档主要讲述的是使用JSON进行网络数据交换传输;JSON(JavaScript ObjectNotation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成,非常适合于服务器与客户端的交互。JSON采用与编程语言无关的文本格式,但是也使用了类C语言的习惯,这些特性使JSON成为理想的数据交换格式。 和 XML 一样,JSON 也是基于纯文本的数据格式。由于 JSON 天生是为 JavaScript 准备的,因此,JSON的数据格式非常简单,您可以用 JSON 传输一个简单的 St
0
应对策略:
dict.get(key, default_value)方法。它会在键不存在时返回default_value(默认为None),而不是抛出错误。
user_info = {"name": "Alice", "age": 25}email = user_info.get("email", "N/A") print(f"用户的邮箱是:{email}")
我个人偏好`get`方法,因为它让代码更健壮,避免了不必要的`try-except`块,特别是在处理可选字段时。
3. 数据类型不匹配
JSON只有少数几种基本类型(字符串、数字、布尔、null、数组、对象),它们会映射到Python的对应类型。但有时候,数据的实际类型可能与你期望的不同。
原因:比如JSON中的数字可能是字符串形式("123"),或者布尔值不是标准的true/false(尽管这通常是JSON格式错误)。
应对策略:
item_data = json.loads('{"id": "123", "is_active": "True"}')item_id = int(item_data.get('id', 0)) is_active = str(item_data.get('is_active', 'False')).lower() == 'true'
print(f"Item ID: {item_id}, Is Active: {is_active}")
这方面,如果你需要更严格的数据验证,可以考虑使用像Pydantic这样的库,它能帮你定义数据模型并自动进行类型转换和校验,非常方便。
将Python对象转换为JSON格式,我们通常追求的不仅仅是转换成功,更希望输出的JSON既能被机器轻松解析,也能在必要时便于人类阅读和调试。json.dumps()和json.dump()提供了一些参数来帮助我们实现这一点。
1. 格式化输出:indent参数
这是最常用的参数之一,它让JSON输出带有缩进,变得“漂亮”起来。
complex_data = {
"project": "Data Analysis Tool",
"version": "1.0.0",
"config": {
"database": {
"type": "PostgreSQL",
"host": "localhost",
"port": 5432
},
"modules": [
{"name": "preprocessing", "enabled": True},
{"name": "visualization", "enabled": False}
]
},
"metadata": {
"author": "开发小李",
"created_at": "2023-10-26T10:00:00Z"
}
}
# 默认输出(紧凑型)
compact_json = json.dumps(complex_data)
print("紧凑型JSON:
", compact_json)
# 带有4个空格缩进的输出
pretty_json = json.dumps(complex_data, indent=4)
print("
格式化JSON (indent=4):
", pretty_json)
# 也可以用制表符缩进
tab_json = json.dumps(complex_data, indent=' ')
print("
格式化JSON (indent='\t'):
", tab_json)在我看来,indent=4几乎是调试和日志输出的标准配置了,可读性极佳。
2. 处理非ASCII字符:ensure_ascii=False
默认情况下,json模块会将所有非ASCII字符转义成uXXXX的形式。这在某些情况下是必要的,比如确保兼容性,但在处理包含中文等语言的JSON时,这会让输出变得难以阅读。设置ensure_ascii=False可以解决这个问题。
chinese_data = {"name": "王小明", "city": "上海"}
# 默认行为:转义非ASCII字符
escaped_json = json.dumps(chinese_data)
print("默认转义:
", escaped_json)
# 不转义非ASCII字符,直接输出
un_escaped_json = json.dumps(chinese_data, ensure_ascii=False, indent=2)
print("
不转义 (ensure_ascii=False):
", un_escaped_json)这个参数在做本地文件存储或内部系统间数据传输时特别有用,能让JSON文件内容更直观。
3. 键排序:sort_keys=True
如果你希望JSON对象的键总是按字母顺序排列,这在某些测试场景或需要保证输出一致性时很有用。
unsorted_data = {"z_key": 1, "a_key": 2, "c_key": 3}
# 默认顺序(Python字典的插入顺序)
default_order_json = json.dumps(unsorted_data, indent=2)
print("默认键顺序:
", default_order_json)
# 按键排序
sorted_key_json = json.dumps(unsorted_data, sort_keys=True, indent=2)
print("
按键排序:
", sorted_key_json)这个功能对于版本控制中的JSON文件差异对比,或者需要确保API响应的JSON结构一致性时,能提供很大的帮助。
4. 处理不可序列化的对象:default参数
这是个稍微高级但非常实用的功能。json模块默认只能序列化Python的基本类型(字符串、数字、布尔、None、列表、字典)。如果你有自定义对象、datetime对象、Decimal对象等,直接dumps会报错TypeError: Object of type X is not JSON serializable。default参数允许你提供一个函数,来处理这些不可序列化的对象。
from datetime import datetime, date
class MyCustomObject:
def __init__(self, name, value):
self.name = name
self.value = value
def to_dict(self): # 一个将自定义对象转换为字典的方法
return {"custom_name": self.name, "custom_value": self.value}
def custom_json_encoder(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat() # 将datetime/date对象转换为ISO格式的字符串
if isinstance(obj, MyCustomObject):
return obj.to_dict() # 调用自定义对象的to_dict方法
raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
data_with_unserializable = {
"event_name": "Project Kickoff",
"event_date": datetime.now(),
"due_date": date(2024, 1, 15),
"manager": MyCustomObject("John Doe", 123)
}
try:
json_output = json.dumps(data_with_unserializable, indent=2, default=custom_json_encoder)
print("
处理自定义对象和日期时间的JSON:
", json_output)
except TypeError as e:
print(f"序列化错误: {e}")这个default参数简直是处理复杂数据结构时的救星。它让我能灵活地定义如何将特定类型的Python对象转换成JSON可识别的格式,而不需要手动遍历整个数据结构进行预处理。
当JSON数据量变得非常庞大,或者数据是以流的形式持续到达时,简单地一次性加载或处理整个JSON字符串可能会导致内存溢出或效率低下。这时,我们需要一些更高级的策略。
1. 内存效率:迭代解析
对于几GB大小的JSON文件,json.load()会尝试将整个文件内容读入内存,这显然是不切实际的。
json模块是为小到中等大小的JSON数据设计的,它倾向于一次性处理整个JSON结构。ijson。ijson库允许你以迭代方式解析JSON数据,它不会一次性将整个JSON树加载到内存中,而是根据需要逐个解析JSON事件(如键、值、数组开始/结束、对象开始/结束)。[{}, {}, ..., {}],ijson可以让你像迭代器一样访问每个内部的对象,而不需要加载整个列表。ijson的API比标准库稍微复杂一些,但它在处理大数据时的内存效率是无与伦比的。我个人觉得,如果你真的碰到了内存瓶颈,ijson绝对值得学习和投入。2. 性能优化:更快的JSON库
Python内置的json模块是用Python实现的,在某些对性能要求极高的场景下,它的速度可能不够快。
json模块可能成为性能瓶颈。json模块兼容的API,但速度要快得多。ujson: 是一个非常流行的选择,提供了json模块的许多核心功能,但速度显著提升。很多时候,你只需要将import json改为import ujson as json就能获得性能提升。orjson: 是另一个性能更极致的库,它声称比ujson更快,并且支持更多高级功能,如处理datetime对象等,无需自定义default函数。pip install ujson或pip install orjson),并且在大多数情况下可以作为标准库json的直接替代品。在我的经验中,如果项目对JSON处理速度有明确要求,我会优先考虑这些C扩展库。这些进阶技巧主要解决的是规模和速度的问题。在日常开发中,标准库的json模块已经足够强大和易用。但当数据量激增或性能成为瓶颈时,了解这些工具能让你从容应对。
以上就是Python如何处理JSON格式数据?解析与转换的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号