最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python處理JSON的完全指南:從基礎(chǔ)到實戰(zhàn),掌握數(shù)據(jù)交換核心技能

 更新時間:2026年06月05日 08:31:04   作者:KeepPush  
本文將從?JSON?與?Python?的類型映射講起,帶你理解序列化與反序列化的底層邏輯,然后通過實戰(zhàn)案例演示如何解析?API?數(shù)據(jù)、處理自定義對象,最后總結(jié)出?3?個避坑技巧

環(huán)境:Python 3.x | 適用人群:Python 初學(xué)者、需要處理 API 數(shù)據(jù)或配置文件的開發(fā)者

你是不是也遇到過這些問題?從 API 接口拿到一串 JSON 數(shù)據(jù),卻不知道如何高效地解析和提取信息;想把 Python 對象保存到文件,卻發(fā)現(xiàn)直接序列化會報錯;或者寫配置文件時,總在逗號、引號這些語法細節(jié)上栽跟頭?JSON 作為現(xiàn)代數(shù)據(jù)交換的“普通話”,是每個 Python 開發(fā)者必須掌握的核心技能。

本文將從 JSON 與 Python 的類型映射講起,帶你理解序列化與反序列化的底層邏輯,然后通過實戰(zhàn)案例演示如何解析 API 數(shù)據(jù)、處理自定義對象,最后總結(jié)出 3 個避坑技巧。讀完本文,你不僅能掌握 json 模塊的所有核心方法,還能獲得一套可直接復(fù)用的代碼模板,輕松應(yīng)對日常開發(fā)中的 JSON 處理需求。

一、JSON 與 Python:類型映射全解析

JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,Python 的 json 模塊提供了兩者間的雙向轉(zhuǎn)換能力。理解它們的類型對應(yīng)關(guān)系是避免后續(xù)錯誤的基礎(chǔ)。

JSON 類型Python 類型示例與注意事項
objectdict{"name": "張三"}{"name": "張三"}
arraylisttuple[1, 2, 3][1, 2, 3]
stringstr"hello""hello"
numberintfloat4242, 3.143.14
true/falseTrue/False注意 Python 首字母大寫
nullNoneJSON 的 null 對應(yīng) Python 的 None

關(guān)鍵區(qū)別:JSON 的鍵必須是字符串(雙引號包裹),而 Python 字典的鍵可以是任何不可變類型(字符串、數(shù)字、元組)。這是序列化時最常見的類型錯誤來源之一。

很多人以為 json.dumps() 會把 Python 的 tuple 也轉(zhuǎn)成 JSON 數(shù)組,這沒錯。但一個隱藏的細節(jié)是:當(dāng) JSON 數(shù)組被 json.loads() 反序列化時,它總是變成 Python 的 list,而不是 tuple。如果你需要元組的不可變性,需要在反序列化后手動轉(zhuǎn)換。

二、Python 到 JSON:序列化實戰(zhàn)與避坑

序列化(Serialization)是將 Python 對象轉(zhuǎn)換為 JSON 字符串的過程,主要通過 json.dumps()(輸出字符串)和 json.dump()(寫入文件)實現(xiàn)。

2.1 基礎(chǔ)序列化:從字典到 JSON 字符串

下面的代碼演示如何將一個包含嵌套結(jié)構(gòu)的 Python 字典轉(zhuǎn)換為格式化的 JSON 字符串:

import json

# 準(zhǔn)備要序列化的數(shù)據(jù)
data = {
    "name": "username",
    "age": 18,
    "is_teacher": False,
    "id": "202205002626",
    "address": {
        "city": "xi an",
        "town": "bigtown"
    }
}

# 基礎(chǔ)轉(zhuǎn)換
json_str = json.dumps(data)
print(f"基礎(chǔ)轉(zhuǎn)換結(jié)果:{json_str}")
print(f"類型:{type(json_str)}")

運行結(jié)果:

基礎(chǔ)轉(zhuǎn)換結(jié)果:{"name": "username", "age": 18, "is_teacher": false, "id": "202205002626", "address": {"city": "xi an", "town": "bigtown"}}
類型:<class 'str'>

Python 內(nèi)部機制json.dumps() 在底層會遞歸遍歷 Python 對象,根據(jù)上述類型映射表進行轉(zhuǎn)換。對于 bool 類型,Python 的 True/False 會被轉(zhuǎn)換為 JSON 的 true/false(小寫)。這個過程在 CPython 中由 C 語言編寫的掃描器完成,速度很快。

2.2 美化輸出:讓 JSON 更易讀

實際開發(fā)中,我們經(jīng)常需要查看或調(diào)試 JSON 數(shù)據(jù),indentensure_ascii 參數(shù)能顯著提升可讀性:

# 美化輸出:縮進、中文支持、鍵排序
json_pretty = json.dumps(
    data,
    indent=2,            # 縮進2個空格
    ensure_ascii=False,  # 中文不轉(zhuǎn)義為 \uXXXX
    sort_keys=True       # 按鍵名字母順序排序
)
print("美化后的 JSON:")
print(json_pretty)

運行結(jié)果:

美化后的 JSON:
{
  "address": {
    "city": "xi an",
    "town": "bigtown"
  },
  "age": 18,
  "id": "202205002626",
  "is_teacher": false,
  "name": "username"
}

2.3 寫入文件:持久化存儲配置

將數(shù)據(jù)保存到文件是配置管理、數(shù)據(jù)緩存的常見場景:

# 將數(shù)據(jù)寫入 JSON 文件
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=2, ensure_ascii=False)
    print("數(shù)據(jù)已成功寫入 data.json 文件")

# 驗證文件內(nèi)容
with open("data.json", "r", encoding="utf-8") as f:
    content = f.read()
    print("文件內(nèi)容預(yù)覽:")
    print(content[:100] + "..." if len(content) > 100 else content)

注意ensure_ascii=False 參數(shù)允許中文字符直接保存,而不是轉(zhuǎn)義為 \uXXXX 格式。但某些舊系統(tǒng)或嚴格遵循 RFC 8259 的解析器可能要求純 ASCII,請根據(jù)實際環(huán)境選擇。寫入文件時指定 encoding='utf-8' 是跨平臺的最佳實踐。

2.4 我踩過的坑:語法錯誤全解析

很多初學(xué)者(包括曾經(jīng)的我)在寫 JSON 或 Python 字典時容易犯以下錯誤:

錯誤1:使用 = 而不是 :

# ? 錯誤寫法
data = {"name" = "username"}  # SyntaxError

# ? 正確寫法
data = {"name": "username"}

錯誤2:鍵值對之間缺少逗號

# ? 錯誤寫法
data = {
    "name": "username"
    "age": 18  # 這里缺少逗號!
}

# ? 正確寫法
data = {
    "name": "username",
    "age": 18  # 每個鍵值對后必須有逗號(最后一個可選)
}

錯誤3:使用中文標(biāo)點

# ? 錯誤寫法(中文逗號)
data = {"name": "username", "age": 18}  # JSONDecodeError

# ? 正確寫法(英文逗號)
data = {"name": "username", "age": 18}

排查技巧:當(dāng)遇到 JSONDecodeError 時,Python 會告訴你出錯的行和列。仔細檢查該位置附近的標(biāo)點符號,90% 的問題都是逗號、引號或冒號使用不當(dāng)。

三、JSON 到 Python:反序列化實戰(zhàn)

反序列化(Deserialization)是將 JSON 字符串轉(zhuǎn)換回 Python 對象的過程,主要通過 json.loads()(從字符串)和 json.load()(從文件)實現(xiàn)。

3.1 從字符串解析:處理 API 響應(yīng)

假設(shè)你從某個 API 接口收到了以下 JSON 字符串:

import json

# 模擬 API 返回的 JSON 字符串
json_str = """{
    "name": "username",
    "age": 18,
    "id": "2022552203"
}"""

print(f"原始字符串:{json_str}")
print(f"字符串類型:{type(json_str)}")

# 反序列化
python_obj = json.loads(json_str)
print(f"\n反序列化結(jié)果:{python_obj}")
print(f"結(jié)果類型:{type(python_obj)}")
print(f"訪問字段 - 姓名:{python_obj['name']}")

運行結(jié)果:

原始字符串:{
    "name": "username",
    "age": 18,
    "id": "2022552203"
}
字符串類型:<class 'str'>

反序列化結(jié)果:{'name': 'username', 'age': 18, 'id': '2022552203'}
結(jié)果類型:<class 'dict'>
訪問字段 - 姓名:username

3.2 從文件讀?。杭虞d配置文件

更常見的場景是從 JSON 配置文件中讀取數(shù)據(jù):

# 從之前創(chuàng)建的 data.json 文件讀取
with open("data.json", "r", encoding="utf-8") as f:
    loaded_data = json.load(f)  # 注意是 load() 不是 loads()
    
print(f"從文件加載的數(shù)據(jù):{loaded_data}")
print(f"數(shù)據(jù)類型:{type(loaded_data)}")
print(f"嵌套訪問 - 城市:{loaded_data['address']['city']}")

3.3 常見反序列化錯誤及解決

錯誤示例1:JSON 語法錯誤

# ? 錯誤寫法:鍵未加雙引號
invalid_json = """{
    name: "username",  # 鍵應(yīng)該用雙引號
    "age": 18
}"""

# ? 錯誤寫法:使用中文逗號
invalid_json2 = """{
    "name": "username",
    "age": 18
}"""

# ? 正確寫法
valid_json = """{
    "name": "username",
    "age": 18
}"""

錯誤示例2:類型不匹配與數(shù)字精度

# JSON 中的數(shù)字可能超出 Python int 范圍
big_num_json = '{"id": 999999999999999999999999999999}'
try:
    result = json.loads(big_num_json)
    print(f"大數(shù)字處理:{result['id']}")  # Python 會自動轉(zhuǎn)為 int
except Exception as e:
    print(f"錯誤:{e}")

# 浮點數(shù)精度問題
float_json = '{"price": 0.1 + 0.2}'  # 這本身是無效JSON,僅作示意
# 實際中,0.1+0.2在JSON中就是0.3,但Python計算0.1+0.2 != 0.3

安全提醒:從不可信來源(如用戶輸入、第三方 API)加載 JSON 時,考慮使用 json.loads()object_hook 參數(shù)進行驗證和過濾,或使用 demjson 等更嚴格的解析器。避免直接 eval() JSON 字符串,以防 JSON 注入攻擊。

四、處理自定義對象:進階序列化技巧

默認情況下,json 模塊無法序列化自定義類的實例。但通過兩種方式可以解決這個問題。

4.1 方法一:自定義編碼器(繼承 JSONEncoder)

這種方法適合需要多次序列化同一類對象的場景,代碼更結(jié)構(gòu)化。

import json

class Person:
    """人員信息類"""
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __repr__(self):
        return f"Person(name={self.name}, age={self.age})"

class PersonEncoder(json.JSONEncoder):
    """自定義 Person 類的 JSON 編碼器"""
    def default(self, obj):
        # 如果是 Person 實例,轉(zhuǎn)換為字典
        if isinstance(obj, Person):
            return {
                "_type": "Person",  # 添加類型標(biāo)記,便于反序列化識別
                "name": obj.name,
                "age": obj.age
            }
        # 其他類型交給父類處理(會拋出 TypeError)
        return super().default(obj)

# 創(chuàng)建 Person 實例
person = Person("張三", 25)

# 使用自定義編碼器序列化
json_str1 = json.dumps(person, cls=PersonEncoder, ensure_ascii=False)
print(f"方法一結(jié)果:{json_str1}")

4.2 方法二:使用 default 回調(diào)函數(shù)

這種方法更靈活,適合臨時處理或多種類型的序列化。

def person_to_dict(obj):
    """將 Person 對象轉(zhuǎn)換為字典的回調(diào)函數(shù)"""
    if isinstance(obj, Person):
        return {
            "_type": "Person",
            "name": obj.name,
            "age": obj.age
        }
    # 如果不是 Person 類型,拋出 TypeError
    raise TypeError(f"對象類型 {type(obj)} 不可序列化")

# 使用 default 參數(shù)序列化
json_str2 = json.dumps(person, default=person_to_dict, ensure_ascii=False)
print(f"方法二結(jié)果:{json_str2}")

兩種方法的輸出相同:

{"_type": "Person", "name": "張三", "age": 25}

4.3 反序列化自定義對象

序列化只是第一步,我們還需要能將 JSON 恢復(fù)為原來的對象:

def dict_to_person(dct):
    """將字典轉(zhuǎn)換回 Person 對象的回調(diào)函數(shù)"""
    if dct.get("_type") == "Person":
        # 根據(jù)字典中的信息重建 Person 對象
        return Person(dct["name"], dct["age"])
    # 如果不是 Person 類型,返回原字典
    return dct

# 反序列化:使用 object_hook 參數(shù)
person_json = '{"_type": "Person", "name": "李四", "age": 30}'
restored_person = json.loads(person_json, object_hook=dict_to_person)

print(f"反序列化結(jié)果:{restored_person}")
print(f"類型:{type(restored_person)}")
print(f"訪問屬性 - 姓名:{restored_person.name}")

運行結(jié)果:

反序列化結(jié)果:Person(name=李四, age=30)
類型:<class '__main__.Person'>
訪問屬性 - 姓名:李四

底層原理object_hook 參數(shù)會在解析每個字典時被調(diào)用。如果返回非字典值,則該值會替換原來的字典。這使得我們可以在解析過程中“攔截”特定格式的字典,將其轉(zhuǎn)換為自定義對象。cls 參數(shù)同理,用于自定義解碼器。

下面用 Mermaid 圖展示自定義對象序列化與反序列化的完整流程:

我第一次實現(xiàn)自定義序列化時踩過一個坑:在 default 方法里沒有處理好繼承關(guān)系。當(dāng)我嘗試序列化一個 Person 的子類 Student 時,isinstance(obj, Person) 判斷為 True,序列化成功了,但反序列化時 object_hook 只認 Person,丟失了子類的特有屬性。解決方案是在字典里也保存類的完整名稱(obj.__class__.__name__),并在 object_hook 里 根據(jù)類名動態(tài)創(chuàng)建對象。

五、實戰(zhàn)項目:解析 API 返回的訂單數(shù)據(jù)

現(xiàn)在我們來完成一個完整的實戰(zhàn)項目:解析一個模擬的電商 API 返回的訂單數(shù)據(jù)。

5.1 準(zhǔn)備測試數(shù)據(jù)

首先創(chuàng)建 pra_json.json 文件,內(nèi)容如下:

{
  "status": 1,
  "message": "success",
  "result": {
    "userInfo": {
      "uid": 5689,
      "username": "study_json",
      "createTime": "2025-08-12"
    },
    "order": [
      {
        "orderNo": "OD20250905001",
        "payMoney": 258.6,
        "product": [
          {"pId": 221, "pName": "Python實戰(zhàn)書籍"},
          {"pId": 222, "pName": "編程配套課程"}
        ]
      },
      {
        "orderNo": "OD20250905002",
        "payMoney": 99,
        "product": [
          {"pId": 315, "pName": "JSON入門手冊"}
        ]
      }
    ]
  }
}

5.2 完整解析代碼

下面的代碼演示了如何穩(wěn)健地解析這個復(fù)雜的嵌套 JSON 結(jié)構(gòu):

import json

def parse_order_data(file_path):
    """
    解析訂單數(shù)據(jù)文件
    
    Args:
        file_path: JSON 文件路徑
        
    Returns:
        dict: 解析后的數(shù)據(jù),包含用戶信息和訂單列表
    """
    try:
        # 1. 讀取并解析 JSON 文件
        with open(file_path, "r", encoding="utf-8") as f:
            data = json.load(f)  # 關(guān)鍵:使用 load() 不是 dumps()
        
        # 2. 檢查接口狀態(tài)
        if data.get("status") != 1:
            print(f"API 請求失敗: {data.get('message', '未知錯誤')}")
            return None
        
        print("? 數(shù)據(jù)獲取成功")
        
        # 3. 提取用戶信息
        user_info = data["result"]["userInfo"]
        print(f"\n?? 用戶信息:")
        print(f"  用戶ID: {user_info['uid']}")
        print(f"  用戶名: {user_info['username']}")
        print(f"  注冊時間: {user_info['createTime']}")
        
        # 4. 提取并處理訂單信息
        orders = data["result"]["order"]
        total_amount = 0!")
運行結(jié)果:

以上就是Python處理JSON的完全指南:從基礎(chǔ)到實戰(zhàn),掌握數(shù)據(jù)交換核心技能的詳細內(nèi)容,更多關(guān)于Python處理JSON的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python精確統(tǒng)計函數(shù)執(zhí)行時間的多種方法

    Python精確統(tǒng)計函數(shù)執(zhí)行時間的多種方法

    在軟件開發(fā)中,我們常常需要了解代碼的執(zhí)行效率,本文將介紹 Python中統(tǒng)計 函數(shù)執(zhí)行時間 的多種方法,及其適用場景和注意事項,需要的朋友可以參考下
    2026-01-01
  • Python基于PyGraphics包實現(xiàn)圖片截取功能的方法

    Python基于PyGraphics包實現(xiàn)圖片截取功能的方法

    這篇文章主要介紹了Python基于PyGraphics包實現(xiàn)圖片截取功能的方法,涉及PyGraphics包的安裝及基于PyGraphics包實現(xiàn)圖片的打開、讀取、截取等相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • 解決webdriver.Chrome()報錯:Message:''chromedriver'' executable needs to be in Path

    解決webdriver.Chrome()報錯:Message:''chromedriver'' executable n

    這篇文章主要介紹了解決webdriver.Chrome()報錯:Message:'chromedriver' executable needs to be in Path ,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • python模仿網(wǎng)頁版微信發(fā)送消息功能

    python模仿網(wǎng)頁版微信發(fā)送消息功能

    這篇文章主要介紹了python模仿網(wǎng)頁版微信發(fā)送消息功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 查看已安裝tensorflow版本的方法示例

    查看已安裝tensorflow版本的方法示例

    這篇文章主要介紹了查看已安裝tensorflow版本的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • pandas 實現(xiàn)將兩列中的較大值組成新的一列

    pandas 實現(xiàn)將兩列中的較大值組成新的一列

    這篇文章主要介紹了pandas 實現(xiàn)將兩列中的較大值組成新的一列,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Pycharm使用CV2的詳細圖文教程

    Pycharm使用CV2的詳細圖文教程

    在Windows操作系統(tǒng)下安裝Python3和OpenCV庫后,通過安裝并配置PyCharm開發(fā)環(huán)境,可以直接顯示并調(diào)用已安裝的包,例如使用cv2庫的接口進行編程和項目開發(fā),文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • Python中列表(List) 的三種遍歷(序號和值)方法小結(jié)

    Python中列表(List) 的三種遍歷(序號和值)方法小結(jié)

    這篇文章主要介紹了Python中列表(List) 的三種遍歷(序號和值)方法小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Python中IPYTHON入門實例

    Python中IPYTHON入門實例

    這篇文章主要介紹了Python中IPYTHON的用法入門,較為詳細的分析了IPYTHON的配置及使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-05-05
  • Python+OpenCV實現(xiàn)邊緣檢測與角點檢測詳解

    Python+OpenCV實現(xiàn)邊緣檢測與角點檢測詳解

    這篇文章主要為大家詳細介紹了如何通過Python+OpenCV實現(xiàn)邊緣檢測與角點檢測,文中的示例代碼講解詳細,對我們學(xué)習(xí)Python與OpenCV有一定的幫助,需要的可以參考一下
    2023-02-02

最新評論

色达县| 斗六市| 日土县| 中方县| 连江县| 阜南县| 本溪市| 南昌县| 河池市| 聂拉木县| 南和县| 辉县市| 彭州市| 浏阳市| 平阴县| 乌兰察布市| 乌拉特后旗| 抚州市| 浦县| 乐至县| 济宁市| 图木舒克市| 淄博市| 永定县| 乐东| 武清区| 杨浦区| 澎湖县| 弥勒县| 屏南县| 景洪市| 民和| 泾阳县| 东城区| 金寨县| 罗山县| 临武县| 宁德市| 靖边县| 汉源县| 宁波市|