從 JSON 到 Python 對象:一次通透的序列化與反序列化之旅

目錄

一、為什么要談 JSON

二、最快速上手:兩把鑰匙 dumps 與 loads

三、深入 dumps:參數是魔法棒

四、深入 loads:把風險擋在門外

五、文件級序列化:dump 與 load

六、處理中文與編碼陷阱

七、異常場景與調試技巧

八、實戰案例:增量保存爬蟲結果

九、對比其他序列化方案

十、總結


一、為什么要談 JSON

如果把程序運行時的內存比喻成熱鬧的城市,那么 JSON 就是連接城市與鄉村的高速公路。城市需要把新鮮果蔬送往鄉村冷庫(持久化),鄉村也要把冷藏好的貨物送回城市(加載)。JSON 憑借“純文本、語言無關、可讀性高”三大優勢,成為公路網中最繁忙的一條。Python 標準庫自帶的高速收費站 json 模塊,讓我們在不安裝任何第三方包的情況下,即可順暢通行。

二、最快速上手:兩把鑰匙 dumps 與 loads

json 模塊最常用的兩把鑰匙只有四個字母:

dumps 把 Python 對象變成 JSON 字符串

loads 把 JSON 字符串還原成 Python 對象

下面給出一段“零門檻”代碼,讓你瞬間體會二者的默契配合。

import jsonperson = {"name": "Alice", "age": 28, "skills": ["Python", "Go"]}# 序列化:Python dict -> JSON str
json_str = json.dumps(person, ensure_ascii=False, indent=2)
print("序列化結果:")
print(json_str)# 反序列化:JSON str -> Python dict
new_person = json.loads(json_str)
print("\n反序列化結果:")
print(new_person, type(new_person))

控制臺會打印出整齊縮進的 JSON,再原封不動地回到字典。ensure_ascii=False 讓中文不再被轉義成 \uXXXX,indent=2 則滿足了人類閱讀的需求。短短七行,就完成了內存與文本之間的第一次握手。

三、深入 dumps:參數是魔法棒

很多人止步于 dumps(obj),卻不知道它還有五個常用參數,可以讓輸出更優雅、體積更小。

  • separators

    默認情況下 dumps 使用 (', ', ': ') 作為分隔符,空格讓 JSON 更美觀,卻讓字節數膨脹。若要把數據塞進網絡包,可以去掉空格。

compact = json.dumps(person, separators=(',', ':'))
print(compact)  # {"name":"Alice","age":28,"skills":["Python","Go"]}
  • sort_keys

    當接口文檔要求字段順序固定時,sort_keys=True 一鍵升序排序,避免肉眼比對差異時抓狂。

  • default

    Python 世界里不只有 dict、list、str、int、float、bool、None,還有 datetime、Decimal、自定義類。JSON 標準并不認識它們,于是 default 充當翻譯官。

from datetime import datetimedef time_converter(o):if isinstance(o, datetime):return o.isoformat()raise TypeError(f"Object of type {type(o)} is not JSON serializable")event = {"created": datetime.utcnow()}
print(json.dumps(event, default=time_converter))
  • skipkeys

    當字典的 key 不是 str、int、float、bool、None 時,默認會拋出 TypeError。設置 skipkeys=True 則靜默跳過這些 key,繼續序列化其余內容,這在調試日志中尤為實用。

四、深入 loads:把風險擋在門外

JSON 字符串可能來自不可信來源,因此 json.loads 提供了嚴格的語法校驗,拒絕一切非法值。除此之外,還有兩個冷門但實用的參數。

  • parse_float

    默認會把帶小數點的數字解析成 float,若你使用 Decimal 避免精度誤差,可以指定解析器。

from decimal import Decimal
data = '{"price": 19.99}'
obj = json.loads(data, parse_float=Decimal)
print(obj["price"], type(obj["price"]))  # 19.99 <class 'decimal.Decimal'>
  • object_hook

    JSON 中的對象都是字典,若你希望直接映射成自定義類,可在反序列化階段動手腳。

class User:def __init__(self, name, age):self.name, self.age = name, agedef __repr__(self):return f"User(name={self.name}, age={self.age})"def dict_to_user(d):if {"name", "age"} <= d.keys():return User(d["name"], d["age"])return djson_user = '{"name": "Bob", "age": 30}'
user_obj = json.loads(json_user, object_hook=dict_to_user)
print(user_obj)  # User(name=Bob, age=30)

五、文件級序列化:dump 與 load

當數據量較大或需要持久化到硬盤時,推薦用 dump 與 load 直接操作文件句柄,避免先把整個 JSON 字符串讀入內存。

data = {"users": [{"id": i, "name": f"user{i}"} for i in range(3)]}# 寫文件
with open("users.json", "w", encoding="utf-8") as f:json.dump(data, f, indent=2, ensure_ascii=False)# 讀文件
with open("users.json", encoding="utf-8") as f:data_back = json.load(f)
print(data_back["users"][0]["name"])  # user0

注意文件必須以文本模式打開,Windows 下若出現換行符困惑,可添加 newline='' 讓 Python 自動處理。

六、處理中文與編碼陷阱

瀏覽器或 Node.js 服務常把中文轉成 \u4e2d\u6587,導致日志不可讀。此時只需在 dumps 中設置 ensure_ascii=False,即可保留原始 UTF-8 字符。此外,文件讀寫顯式指定 encoding='utf-8' 可防止跨平臺亂碼。

七、異常場景與調試技巧

  1. TypeError: Object of type set is not JSON serializable
    集合 set 不是 JSON 基本類型,可先用 list() 轉換。

  2. JSONDecodeError: Expecting property name
    字符串末尾多余逗號、單引號未轉義都會導致解析失敗,可使用 json.tool 命令行工具格式化校驗。

  3. 性能瓶頸
    大量數據循環調用 dumps 會觸發頻繁內存分配,可一次性構建大字典再序列化,或改用第三方庫 orjson、ujson。

八、實戰案例:增量保存爬蟲結果

假設我們在爬取 GitHub API,每 100 條記錄保存一次中間結果,防止程序崩潰丟失進度。

import requests, json, osdef crawl_and_save(keyword, pages=5):all_items = []for page in range(1, pages + 1):url = f"https://api.github.com/search/repositories?q={keyword}&page={page}"resp = requests.get(url, timeout=10)resp.raise_for_status()items = resp.json()["items"]all_items.extend(items)# 增量保存with open(f"github_{keyword}_page{page}.json", "w", encoding="utf-8") as f:json.dump(items, f, ensure_ascii=False, indent=2)# 合并結果with open(f"github_{keyword}_all.json", "w", encoding="utf-8") as f:json.dump(all_items, f, ensure_ascii=False, indent=2)if __name__ == "__main__":crawl_and_save("python", 3)

九、對比其他序列化方案

JSON 的優勢是“人讀、跨語言”,劣勢是“不支持復雜類型、體積較大”。如果需要更高性能或支持 Python 特有對象,可考慮:

  • pickle:速度快、支持任意對象,但僅限 Python 且存在安全風險。

  • MessagePack:二進制 JSON,體積更小,跨語言。

  • Protobuf:IDL 驅動,適合大型分布式系統。
    選擇方案時,不要只追求技術酷炫,而應結合可讀性、兼容性、性能三角平衡。

十、總結

序列化是把“活的” Python 對象變成“可運輸”文本的過程,反序列化則是逆向復活。json 模塊提供了簡潔而強大的 API,讓我們以極低的成本完成數據持久化、網絡傳輸、配置管理。掌握 dumps、loads、dump、load 的細粒度參數,就能在優雅、安全、高效之間游刃有余。下次當你寫接口、寫爬蟲、寫工具腳本時,別忘了這條最熟悉也最容易被忽視的 JSON 高速通道。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914505.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914505.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914505.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Leetcode 3315. 構造最小位運算數組 II

1.題目基本信息 1.1.題目描述 給你一個長度為 n 的質數數組 nums 。你的任務是返回一個長度為 n 的數組 ans &#xff0c;對于每個下標 i &#xff0c;以下 條件 均成立&#xff1a; ans[i] OR (ans[i] 1) nums[i] 除此以外&#xff0c;你需要 最小化 結果數組里每一個 a…

黑搜小知識 | DNS域名解析過程是什么樣的?

什么是DNS&#xff1f;DNS( Domain Name System)是“域名系統”的英文縮寫&#xff0c;是一種組織成域層次結構的計算機和網絡服務命名系統&#xff0c;它用于TCP/IP網絡&#xff0c;它所提供的服務是用來將主機名和域名轉換為IP地址的工作。舉例來說&#xff0c;如果你要訪問域…

MyBatis 使用教程及插件開發

作者&#xff1a;小凱 沉淀、分享、成長&#xff0c;讓自己和他人都能有所收獲&#xff01; 本文的宗旨在于通過簡單干凈實踐的方式教會讀者&#xff0c;使用 SpringBoot 配置 MyBatis 并完成對插入、批量插入、修改、查詢以及注解事務和編程事務的使用&#xff0c;通過擴展插件…

Maui勸退:用windows直接真機調試iOS,無須和Mac配對

初級代碼游戲的專欄介紹與文章目錄-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代碼都將會位于ctfc庫中。已經放入庫中我會指出在庫中的位置。 這些代碼大部分以Linux為目標但部分代碼是純C的&#xff0c;可以在任何平臺上使用。 源碼指引&#xff1a;github源…

【極客日常】后端任務動態注入執行策略的一種技術實現

近期做項目時遇到一個場景&#xff0c;是需要在后端任務執行時動態注入策略。具體而言&#xff0c;筆者負責的后端服務&#xff0c;可以理解是會在線上服務發布時&#xff0c;對服務風險做實時掃描&#xff0c;那么這個掃描就需要根據當前線上服務發布上下文&#xff0c;匹配對…

8. JVM類裝載的執行過程

1. JVM介紹和運行流程-CSDN博客 2. 什么是程序計數器-CSDN博客 3. java 堆和 JVM 內存結構-CSDN博客 4. 虛擬機棧-CSDN博客 5. JVM 的方法區-CSDN博客 6. JVM直接內存-CSDN博客 7. JVM類加載器與雙親委派模型-CSDN博客 8. JVM類裝載的執行過程-CSDN博客 9. JVM垃圾回收…

Linux操作系統之信號:信號的產生

前言&#xff1a;上篇文章我們大致講解了信號的有關概念&#xff0c;為大家引入了信號的知識點。但光知道那些是遠遠不夠的。本篇文章&#xff0c;我將會為大家自己的講解一下信號的產生的五種方式&#xff0c;希望對大家有所幫助。一、鍵盤&#xff08;硬件&#xff09;產生信…

pdf拆分

文章目錄 背景目標實現下載 背景 好不容易下載的1000頁行業報告&#xff0c;領導非要按章節拆分成20份&#xff01;學術論文合集需要按作者拆分投稿&#xff0c;手動分頁到懷疑人生…客戶發來加密合同&#xff0c;要求每5頁生成獨立文檔&#xff0c;格式還不能亂&#xff01; …

vue3使用mermaid生成圖表,并可編輯

效果圖實際代碼<template><div class"mermaid-container" style"z-index: 99999" ref"wrapperRef"><!-- 控制欄 --><div class"control-bar"><div class"control-bar-flex control-bar-tab-wrap"…

tcp/quic 的滑動窗口

一、滑動窗口 rwnd&#xff1a; 接收端窗口&#xff0c;接收方在每次發送ACK確認報文時&#xff0c;會包含一個 rwnd (Receive Window Size) 字段&#xff0c;指明自己當前剩余的接收緩沖區大小&#xff08;即可用窗口&#xff09;&#xff0c;這里是否是socket的接收緩沖區&am…

JVM監控及診斷工具-命令行篇

18.1. 概述 性能診斷是軟件工程師在日常工作中需要經常面對和解決的問題&#xff0c;在用戶體驗至上的今天&#xff0c;解決好應用的性能問題能帶來非常大的收益。 Java 作為最流行的編程語言之一&#xff0c;其應用性能診斷一直受到業界廣泛關注。可能造成 Java 應用出現性能…

Jenkins 版本升級與插件問題深度復盤:從 2.443 到 2.504.3 及功能恢復全解析

前言&#xff1a;問題溯源與升級必要性 在 Jenkins 持續集成體系中&#xff0c;插件生態是其強大功能的核心驅動力。然而&#xff0c;某次例行維護中&#xff0c;團隊對 Jenkins 2.443 環境的插件進行批量升級后&#xff0c;意外觸發連鎖反應 &#xff1a; SSH Server 插件功能…

Ribbon實戰

一、前置知識 1.1 負載均衡定義 負載均衡指的是將網絡請求通過不同的算法分配到不同的服務器上的技術&#xff0c;從而提升系統的性能。 1.2 負載均衡工具 負載均衡工具可以分分為客戶端負載均衡工具和服務端負載均衡工具&#xff0c;它們的區別如下。 表1-1 負載均衡工具…

cs285學習筆記(一):課程總覽

根據 Fall 2023 學期的官方課程日程&#xff0c;這里是 CS?285 全課程的 Lecture 大綱及內容摘要&#xff0c;詳細對應周次和主題&#xff0c;方便你快速定位每節課要點、相關作業與視頻資源 &#x1f3af; 官方課程地址 YouTobe 視頻地址 blibli視頻(帶中文字幕) &#x…

OkHttp SSE 完整總結(最終版)

1. SSE 基礎概念 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent Events&#xff09;是一種 Web 標準&#xff0c;允許服務器向客戶端推送實時數據。 核心特點 單向通信&#xff1a;服務器 → 客戶端 基于 HTTP 協議&#xff1a;使用 GET 請求 長連接&#xff1a;連…

聚寬sql數據庫傳遞

自建數據庫從聚寬到Q-MT自動化交易實戰 從接觸聚寬以來一直都是手動跟單&#xff0c;在網上看到許多大佬的自動交易文章&#xff0c;心里也不禁十分癢癢。百說不如一練&#xff0c;千講不如實干。經過一番努力&#xff0c;終于成功實盤了&#xff0c;效果還可以&#xff0c;幾…

es里為什么node和shard不是一對一的關系

提問&#xff1a; 既然多個shard會被分配到同一個node上&#xff0c;那么為什么不把多個shard合并成一個然后存在當前node上呢&#xff0c;簡而言之也就是讓node和shard形成一對一的關系呢 &#xff1f;非常好的問題&#xff0c;這正是理解Elasticsearch分片&#xff08;shard…

淺談npm,cnpm,pnpm,npx,nvm,yarn之間的區別

首先做一個基本的分類 名稱描述npm,cnpm,yarn,pnpm都是Javascript包管理器nvm是Node.js版本控制器npx命令行工具 I.npm,cnpm,yarn,pnpm npm (Node Package Manager) npm是Node.js默認的包管理器&#xff0c;隨Node.js的安裝會一起安裝。使用npm可以安裝&#xff0c;發布&…

滑動窗口-76.最小覆蓋子串-力扣(LeetCode)

一、題目解析1.不符合要求則返回空串("")2.子串中重復字符的數量要不少于t中該字符的數量二、算法原理解法1&#xff1a;暴力枚舉哈希表這里的暴力枚舉也可以優化&#xff0c;即在包含t中元素處枚舉&#xff0c;如在A、B和C處開始枚舉&#xff0c;減少不必要的枚舉 解…

從零構建搜索引擎 build demo search engine from scratch

從零構建搜索引擎 build demo search engine from scratch 我們每天都會使用搜索引擎&#xff1a;打開google等搜索引擎&#xff0c;輸入關鍵詞&#xff0c;檢索出結果&#xff0c;這是一次搜索&#xff1b;當打開歷史記錄旁邊的&#x1f50d;按鈕&#xff0c;輸入關鍵詞&#…