python操作json的核心是使用json模塊的四個函數。1.json.loads()將json字符串轉為python對象;2.json.dumps()將python對象轉為json字符串,可設置indent美化格式;3.json.load()從文件讀取json數據;4.json.dump()將python數據寫入json文件。常見問題包括編碼錯誤、數據類型不匹配和json解析異常,需注意ensure_ascii=false支持中文、處理布爾值與none的轉換及捕獲jsondecodeerror。對于嵌套結構,可通過鏈式訪問逐層提取數據,結合.get()方法安全處理缺失字段。
在Python里操作JSON,其實遠沒有聽起來那么復雜。核心就是利用Python自帶的json模塊,它能幫你輕松實現Python數據結構(比如字典和列表)與JSON字符串之間的轉換。無論是從文件讀取,還是把數據寫入文件,亦或是直接處理內存中的字符串,json模塊都提供了直觀且強大的接口。
解決方案
要用Python操作JSON,你主要會用到json.loads()、json.dumps()、json.load()和json.dump()這四個函數。
-
從JSON字符串加載數據到Python對象:json.loads() 當你手頭有一個JSON格式的字符串,想把它變成Python能理解的字典或列表時,loads(load String的縮寫)就是你的首選。
import json json_str = '{"name": "張三", "age": 30, "isStudent": false, "courses": ["Math", "Physics"]}' data = json.loads(json_str) print(data) print(type(data)) # 輸出:{'name': '張三', 'age': 30, 'isStudent': False, 'courses': ['Math', 'Physics']} # 輸出:<class 'dict'>
-
將Python對象轉換為JSON字符串:json.dumps() 反過來,如果你有一個Python字典或列表,想把它序列化成JSON格式的字符串,以便存儲、傳輸或打印,dumps(dump string的縮寫)就派上用場了。
import json py_dict = { "title": "Python JSON操作指南", "author": "一個愛折騰的開發者", "tags": ["Python", "JSON", "數據處理"], "version": 1.0 } json_output = json.dumps(py_dict, indent=4, ensure_ascii=False) # indent用于美化輸出,ensure_ascii=False支持中文 print(json_output) # 輸出: # { # "title": "Python JSON操作指南", # "author": "一個愛折騰的開發者", # "tags": [ # "Python", # "JSON", # "數據處理" # ], # "version": 1.0 # }
-
從JSON文件加載數據到Python對象:json.load() 處理文件時,load(注意沒有’s’)能直接從打開的文件對象中讀取JSON數據。這比先讀取整個文件內容到字符串再用loads效率更高,也更方便。 假設你有一個名為data.json的文件,內容是:
{ "city": "北京", "temperature": 25, "forecast": ["晴", "多云"] }
import json try: with open('data.json', 'r', encoding='utf-8') as f: file_data = json.load(f) print(file_data) # 輸出:{'city': '北京', 'temperature': 25, 'forecast': ['晴', '多云']} except FileNotFoundError: print("文件 data.json 不存在,請先創建。")
-
將Python對象寫入JSON文件:json.dump() 要將Python對象直接寫入JSON文件,使用dump。它會幫你處理文件寫入的細節,同樣可以指定indent參數讓文件內容更易讀。
import json new_data = { "product": "智能音箱", "price": 399.99, "features": ["語音控制", "藍牙連接", "智能家居"] } with open('output.json', 'w', encoding='utf-8') as f: json.dump(new_data, f, indent=4, ensure_ascii=False) print("數據已成功寫入 output.json 文件。") # output.json 的內容會是格式化后的JSON
Python處理JSON數據時常見的錯誤與應對策略
說實話,剛開始用Python處理JSON,踩坑是常有的事。最常見的幾個問題,我個人經驗來看,主要集中在編碼、數據類型不匹配和錯誤處理上。
立即學習“Python免費學習筆記(深入)”;
一個很典型的錯誤就是編碼問題。當你從外部文件或網絡請求獲取JSON數據時,如果文件的編碼不是UTF-8,或者你的程序沒有正確指定編碼,就很容易遇到UnicodeDecodeError。JSON標準建議使用UTF-8,所以我的習慣是,無論讀寫文件,都明確加上encoding=’utf-8’。比如,open(‘file.json’, ‘r’, encoding=’utf-8′)。這能省去很多不必要的麻煩。
再來是數據類型映射的理解偏差。Python的None在JSON里對應的是NULL,Python的True/False對應的是true/false。如果你不小心把Python的布爾值當字符串存進去,或者反過來期望JSON的null能直接被Python識別成某個特定值,就可能出問題。json模塊會自動幫你處理這些基本類型的轉換,但如果你在Python代碼里構造數據時用了非JSON兼容的類型(比如set),json.dumps()就會拋出TypeError。這時候你就得手動轉換,比如把set轉成list。
最后,也是我經常強調的,錯誤處理。不是所有的字符串都是合法的JSON。當json.loads()嘗試解析一個格式錯誤的字符串時,它會拋出json.JSONDecodeError。所以,在實際項目中,尤其是在處理用戶輸入或外部API返回的數據時,一定要用try…except json.JSONDecodeError來捕獲這個異常。這樣可以防止程序崩潰,并給用戶或日志提供有用的錯誤信息。
import json malformed_json_str = '{"name": "Alice", "age": 30,' # 少了個 } try: data = json.loads(malformed_json_str) print(data) except json.JSONDecodeError as e: print(f"解析JSON失敗:{e}") print("請檢查JSON字符串的格式是否正確。") # 輸出:解析JSON失?。篍xpecting property name or '}' at line 1 column 28 (char 27) # 輸出:請檢查JSON字符串的格式是否正確。
如何優雅地美化和格式化JSON輸出?
讓JSON輸出變得“好看”或者說“易讀”,是調試和日志記錄時非常重要的一個環節。json模塊提供了幾個參數,能讓你輕松實現這一點。我個人在調試或者需要把JSON內容粘貼到文檔里時,都會用到它們。
最常用的就是indent參數。當你把它設置為一個整數(比如4)時,json.dumps()或json.dump()會在每個層級縮進指定數量的空格,并為每個鍵值對添加換行符,讓JSON結構一目了然。
import json complex_data = { "project": "ai助手", "developers": [ {"name": "李華", "role": "前端"}, {"name": "王明", "role": "后端", "skills": ["Python", "Django", "SQL"]} ], "status": "開發中", "milestones": { "phase1": "需求分析", "phase2": "原型設計", "phase3": "核心功能開發" } } # 不帶縮進的輸出,緊湊但難以閱讀 print("--- 緊湊輸出 ---") print(json.dumps(complex_data, ensure_ascii=False)) # 帶4個空格縮進的輸出,非常易讀 print("n--- 格式化輸出 (indent=4) ---") print(json.dumps(complex_data, indent=4, ensure_ascii=False))
除了indent,還有一個sort_keys參數也很有用。當sort_keys設置為True時,輸出的JSON中,字典的鍵會按照字母順序排序。這對于需要比較兩個JSON文件是否完全相同(例如,自動化測試中對比預期輸出和實際輸出),或者僅僅是為了保持輸出的一致性,都非常有幫助。因為JSON對象中的鍵是無序的,不同次運行dumps可能會得到鍵順序不同的字符串,sort_keys=True就能解決這個問題。
import json data_to_sort = { "z_key": 1, "a_key": 2, "c_key": 3 } print("n--- 默認鍵順序 (不保證) ---") print(json.dumps(data_to_sort, indent=2)) print("n--- 排序后的鍵順序 ---") print(json.dumps(data_to_sort, indent=2, sort_keys=True))
通過這些參數,你可以根據不同的場景需求,靈活地控制JSON輸出的格式,讓它們要么緊湊高效,要么清晰易讀。
處理嵌套JSON數據有哪些技巧?
JSON數據結構最迷人的地方,就是它天然支持嵌套。一個鍵的值可以是另一個JSON對象,也可以是json數組,數組里面又可以包含JSON對象……這種層層疊疊的結構,在表示復雜關系時特別方便。但處理起來,有時候確實會讓人感覺像在“剝洋蔥”。
核心技巧就是鏈式訪問。Python在把JSON解析成字典和列表后,你就可以像操作普通Python字典和列表一樣,一層一層地訪問下去。
import json nested_json_str = """ { "company": "TechSolutions Inc.", "departments": [ { "name": "研發部", "employees": [ {"id": "001", "name": "王工程師", "projects": ["Project Alpha", "Project Beta"]}, {"id": "002", "name": "李架構師", "projects": ["Project Gamma"]} ], "location": {"city": "上海", "building": "A座"} }, { "name": "市場部", "employees": [ {"id": "003", "name": "張經理", "campaigns": ["Spring Sale"]} ], "location": {"city": "北京", "building": "B座"} } ], "established_year": 2010 } """ data = json.loads(nested_json_str) # 訪問公司名稱 print(f"公司名稱: {data['company']}") # 訪問第一個部門的名稱 first_department = data['departments'][0] print(f"第一個部門: {first_department['name']}") # 訪問第一個部門的第二個員工的名字和項目 second_employee = first_department['employees'][1] print(f"第二個員工: {second_employee['name']}, 參與項目: {second_employee['projects']}") # 訪問第二個部門的城市 second_department_city = data['departments'][1]['location']['city'] print(f"第二個部門所在城市: {second_department_city}")
當數據結構變得非常復雜,或者你不確定某個鍵是否存在時,使用字典的.get()方法會比直接用[]訪問更安全。get()方法允許你提供一個默認值,當鍵不存在時返回這個默認值,而不是拋出KeyError。這在處理可能缺失字段的JSON數據時尤其有用。
# 假設我們想獲取一個可能不存在的部門 try: non_existent_department = data['departments'][2] # 索引2不存在 print(non_existent_department) except IndexError: print("部門索引超出范圍。") # 使用 .get() 訪問可能不存在的鍵 # 嘗試獲取一個不存在的員工ID employee_id = data['departments'][0]['employees'][0].get('employee_id', 'N/A') print(f"員工ID (可能不存在): {employee_id}") # 輸出:員工ID (可能不存在): N/A # 嘗試獲取一個不存在的部門名稱,返回None non_existent_dept_name = data.get('non_existent_department', {}).get('name') print(f"不存在的部門名稱: {non_existent_dept_name}") # 輸出:不存在的部門名稱: None
對于非常深層或結構不固定的JSON,你可能需要編寫遞歸函數來遍歷整個結構,或者考慮使用jsonpath這樣的第三方庫,它們提供了類似XPath的查詢語言來定位JSON中的特定元素。但對于大多數日常任務,掌握鏈式訪問和.get()方法,就已經足夠應對了。