Python處理JSON的四大函數(shù)全解析(load/loads/dump/dumps)
在現(xiàn)代軟件開發(fā)中,JSON (JavaScript Object Notation) 已成為數(shù)據(jù)交換的通用語言。無論是與 Web API 通信、存儲應用程序配置,還是在不同服務間傳遞信息,JSON 的身影無處不在。Python 憑借其強大的標準庫,內(nèi)置了功能完備的 json 模塊來應對這一切。
然而,對于許多初學者來說,load、loads、dump、dumps 這四個核心函數(shù)似乎總是有點令人困惑。它們的名字如此相似,功能又各有側(cè)重。本文將徹底厘清它們的區(qū)別,從基礎用法到高級技巧,在處理 JSON 數(shù)據(jù)時游刃有余。
一、核心法則:解密神秘的s后綴
要掌握這四個函數(shù),我們首先要理解一個最關(guān)鍵的區(qū)別:函數(shù)名末尾的 s。
這里的 s 代表 string (字符串)。
- 帶 s 的函數(shù) (loads, dumps): 它們操作的對象是內(nèi)存中的 Python 字符串。
- 不帶 s 的函數(shù) (load, dump): 它們操作的對象是 文件(或類文件)對象,負責數(shù)據(jù)的讀寫。
記住這個“黃金法則”,就已經(jīng)掌握了它們一半的奧秘。接下來,圍繞兩大核心操作——序列化和反序列化來展開。
1、序列化:將 Python 對象轉(zhuǎn)換為 JSON
序列化(也稱編碼)是將 Python 對象(如字典或列表)轉(zhuǎn)換為 JSON 格式的過程。
1.1 json.dumps(): 轉(zhuǎn)換成 JSON字符串
當需要將一個 Python 對象變成一個 JSON 格式的字符串,以便通過網(wǎng)絡發(fā)送或在程序中進一步處理時,dumps() 是不二之選。
import json
# 一個 Python 字典
data = {
"name": "張三",
"age": 30,
"courses": ["數(shù)學", "英語"]
}
# 轉(zhuǎn)換為 JSON 字符串
# ensure_ascii=False 確保中文字符正常顯示
# indent=4 讓輸出格式更美觀
json_string = json.dumps(data, ensure_ascii=False, indent=4)
print("轉(zhuǎn)換后的 JSON 字符串:")
print(json_string)
print("\n類型是:", type(json_string))運行結(jié)果:

1.2 json.dump(): 寫入到 JSON文件
當需要將數(shù)據(jù)持久化存儲,例如保存配置文件或程序狀態(tài)時,dump() 可以直接將 Python 對象寫入文件中。
import json
data = {
"name": "李四",
"age": 25,
"courses": ["數(shù)學", "英語"]
}
# 'w' 表示寫入模式,encoding='utf-8' 支持中文
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
print("數(shù)據(jù)已成功寫入 data.json 文件。")1.3ensure_ascii 詳解
ensure_ascii 是 json.dump() 和 json.dumps() 函數(shù)中的一個布爾類型參數(shù),它控制著輸出結(jié)果中如何處理非 ASCII 字符(例如中文、日文、特殊符號等)。
當調(diào)用 json.dumps() 或 json.dump() 而不指定 ensure_ascii 參數(shù)時,它默認為 True。在這種模式下,所有非 ASCII 字符都會被“轉(zhuǎn)義”成 \uXXXX 的形式。\uXXXX 是一種 Unicode 轉(zhuǎn)義序列。這種做法的初衷是為了保證最大的兼容性。因為 ASCII 編碼是計算機世界里最基礎、最通用的字符集,任何系統(tǒng)都可以無誤地處理純 ASCII 文本。通過將所有特殊字符轉(zhuǎn)換為 ASCII 范圍內(nèi)的 \u 序列,可以確保生成的 JSON 字符串在任何環(huán)境下(即使是那些不支持 UTF-8 的老舊系統(tǒng))都能被安全地傳輸和存儲,不會產(chǎn)生編碼錯誤或亂碼。
推薦:當明確地將 ensure_ascii 設置為 False 時,是在告訴 json 模塊:“請不要轉(zhuǎn)義這些非 ASCII 字符,直接將它們原樣輸出。”
注意:當使用 ensure_ascii=False 并且要將結(jié)果寫入文件 (json.dump()) 時,有一個非常重要的配套操作:必須在 open() 函數(shù)中指定編碼,通常是 encoding='utf-8'。ensure_ascii=False 產(chǎn)生了包含原生非 ASCII 字符的輸出。如果不指定編碼,Python 可能會使用操作系統(tǒng)的默認編碼(在某些 Windows 系統(tǒng)上可能是 GBK 或 CP936)來嘗試寫入文件。此時如果字符(比如某些特殊符號或生僻字)不在該默認編碼范圍內(nèi),程序就會拋出 UnicodeEncodeError 錯誤。
在今天,UTF-8 已經(jīng)成為事實上的標準。因此,在 Python 項目中,強烈推薦始終使用 ensure_ascii=False 并配合 encoding='utf-8' 來處理 JSON 數(shù)據(jù)。這會讓數(shù)據(jù)文件更易于管理、調(diào)試,也更節(jié)省空間。
2、反序列化:將 JSON 解析為 Python 對象
2.1 json.loads(): 從 JSON字符串中加載
從 API 響應或消息隊列中收到一個 JSON 格式的字符串時,loads() 會將其解析為 Python 的字典或列表。
import json
json_string = '''
{
"name": "王五",
"isAlive": true,
"hobbies": ["籃球", "游戲"]
}
'''
# 從字符串加載
python_dict = json.loads(json_string)
print("轉(zhuǎn)換后的 Python 字典:")
print(python_dict)
print("\n類型是:", type(python_dict))
print("姓名是:", python_dict["name"])運行結(jié)果:

2.2 json.load(): 從 JSON文件中讀取
當需要從一個配置文件(如 user_data.json)中讀取數(shù)據(jù)并加載到程序中時,load() 是最直接的方法。
import json
# 'r' 表示讀取模式,encoding='utf-8' 支持中文
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
print("從文件讀取的數(shù)據(jù):")
print(data)
print("\n類型是:", type(data))
print("課程是:", data["courses"])3、表格對比
| 函數(shù) | 操作 | 輸入 | 輸出 | 主要用途 |
| json.dumps() | 序列化 | Python 對象 | JSON 格式的字符串 | 網(wǎng)絡傳輸、內(nèi)存處理 |
| json.dump() | 序列化 | Python 對象 + 文件對象 | None (寫入文件) | 數(shù)據(jù)持久化、保存配置 |
| json.loads() | 反序列化 | JSON 格式的字符串 | Python 對象 | 解析 API 響應、文本數(shù)據(jù) |
| json.load() | 反序列化 | 文件對象 | Python 對象 | 從文件加載配置或數(shù)據(jù) |
二、超越基礎:json模塊的進階工具
上述四個函數(shù)能滿足 99% 的需求,同時在某些特殊場景下,json 模塊還提供了更強大的工具:
1、處理自定義對象 (JSONEncoder)
當試圖序列化一個 Python 自定義對象(比如一個類的實例)時,json.dumps() 默認是不知道如何處理的,會拋出 TypeError。為了解決這個問題,json 模塊提供了 JSONEncoder 和 JSONDecoder 類。
json.JSONEncoder: 你可以通過繼承這個類并重寫 default() 方法,來告訴 dumps 如何處理你自定義的數(shù)據(jù)類型。場景示例:你想將一個包含 datetime 對象的字典序列化,但 JSON 標準里沒有日期時間類型。
import json
from datetime import datetime
# 默認情況下,這會報錯
# data = {'name': 'test', 'time': datetime.now()}
# json.dumps(data) # TypeError: Object of type datetime is not JSON serializable
# 使用自定義 Encoder
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
# 將 datetime 對象格式化為字符串
return obj.isoformat()
# 其他類型調(diào)用父類的默認處理方法
return super().default(obj)
data = {'name': 'test', 'time': datetime.now()}
json_string = json.dumps(data, cls=DateTimeEncoder, indent=4)
print(json_string)
# 輸出:
# {
# "name": "test",
# "time": "2025-10-06T22:01:28.123456"
# }json.JSONDecoder: 與上面對應,可以通過繼承這個類,使用 object_hook 參數(shù)來定義如何將特定的 JSON 數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換回自定義的 Python 對象。
import json
from datetime import datetime
def datetime_decoder_hook(json_dict):
"""
一個用于 json.loads 的 object_hook 函數(shù)。
它會檢查字典中的值,嘗試將符合 ISO 8601 格式的字符串轉(zhuǎn)換回 datetime 對象。
"""
for key, value in json_dict.items():
# 檢查值是否為字符串,并嘗試進行轉(zhuǎn)換
if isinstance(value, str):
try:
# 嘗試用 fromisoformat 解析
# Python 3.7+ 支持解析帶 Z 和微秒的完整 ISO 格式
json_dict[key] = datetime.fromisoformat(value)
except (ValueError, TypeError):
# 如果轉(zhuǎn)換失?。ㄕf明它不是我們想要的日期格式),則保持原樣
pass
return json_dict
# 1. 準備一個包含 ISO 日期格式字符串的 JSON
json_string = """
{
"name": "test_event",
"user_id": 123,
"created_at": "2025-10-06T22:01:28.123456",
"metadata": {
"source": "api",
"processed_at": "2025-10-07T10:55:00.543210"
}
}
"""
# 2. 使用 object_hook 進行解碼
data_with_datetime = json.loads(json_string, object_hook=datetime_decoder_hook)
# 3. 驗證結(jié)果
print("解碼后的 Python 對象:")
print(data_with_datetime)
print("\n--- 類型驗證 ---")
print(f"'created_at' 的類型是: {type(data_with_datetime['created_at'])}")
print(f"'processed_at' 的類型是: {type(data_with_datetime['metadata']['processed_at'])}")
print(f"'name' 的類型是: {type(data_with_datetime['name'])}")運行結(jié)果:

直接使用 object_hook 參數(shù)通常是最簡單直接的方式。但如果想創(chuàng)建一個可重用的、配置更復雜的解碼器,或者在某個類中封裝解碼邏輯,也可以選擇繼承 json.JSONDecoder。
import json
from datetime import datetime
class CustomDateTimeDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
# 將我們的鉤子函數(shù)綁定到解碼器實例上
json.JSONDecoder.__init__(self, object_hook=self.datetime_hook, *args, **kwargs)
def datetime_hook(self, json_dict):
for key, value in json_dict.items():
if isinstance(value, str):
try:
json_dict[key] = datetime.fromisoformat(value)
except (ValueError, TypeError):
pass
return json_dict
# 使用自定義的解碼器類
json_string = '{"name": "test", "time": "2025-10-06T22:01:28.123456"}'
# 通過 cls 參數(shù)傳入自定義的解碼器類
data = json.loads(json_string, cls=CustomDateTimeDecoder)
print(data)
print(f"time 字段的類型是: {type(data['time'])}")2、健壯的錯誤處理 (JSONDecodeError):
當解析格式錯誤的 JSON 時,程序會拋出 json.JSONDecodeError。在生產(chǎn)環(huán)境中,應該使用 try...except 塊來捕獲這個異常,避免程序因此崩潰。
場景示例:從一個 API 獲取了一段不完整的 JSON 字符串。
import json
invalid_json = '{"name": "John", "age": 30,' # 注意這里缺少了結(jié)尾的 '}'
try:
data = json.loads(invalid_json)
except json.JSONDecodeError as e:
print(f"JSON 解析失敗: {e}")
# 輸出: JSON 解析失敗: Unexpected end of document: line 1 column 29 (char 28)3、便捷的命令行工具(json.tool):
Python 提供了一個方便的命令行工具,可以快速驗證 JSON 文件的合法性并將其格式化輸出。只需在終端運行 python -m json.tool your_file.json 即可。
三、總結(jié)
| 功能分類 | 主要成員 | 用途 | 使用頻率 |
| 核心功能 | load, loads, dump, dumps | 在 Python 對象和 JSON 之間進行轉(zhuǎn)換(文件/字符串) | 非常高 (99%) |
| 高級定制 | JSONEncoder, JSONDecoder | 處理非標準/自定義數(shù)據(jù)類型的序列化和反序列化 | 較低 |
| 錯誤處理 | JSONDecodeError | 捕獲和處理格式錯誤的 JSON 數(shù)據(jù) | 中等(在生產(chǎn)代碼中很重要) |
| 命令行工具 | json.tool | 從命令行快速驗證和格式化 JSON 文件 | 偶爾(對開發(fā)者調(diào)試很有用) |
到此這篇關(guān)于Python處理JSON的四大函數(shù)全解析(load/loads/dump/dumps)的文章就介紹到這了,更多相關(guān)Python處理JSON內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Tensorflow卷積神經(jīng)網(wǎng)絡實例進階
這篇文章主要為大家詳細介紹了Tensorflow卷積神經(jīng)網(wǎng)絡實例進階,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05
使用OpenCV實現(xiàn)仿射變換—旋轉(zhuǎn)功能
這篇文章主要介紹了在OpenCV里實現(xiàn)仿射變換——旋轉(zhuǎn)功能,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-08

