使用Python和PyQt5打造一個JSON快速查看器
最近寫了一個小工具:只要拖入或打開一個 JSON 文件,輸入 KEY,就能快速查看對應的值。本文以 d:\測試\Github項目\59-JOSN快速查看器\main.py 為例,完整拆解這個 PyQt5 小工具的實現(xiàn)思路和關(guān)鍵代碼。
一、需求與效果
需求非常簡單:
- 支持從文件拖拽或文件選擇框加載 JSON 文件
- 輸入 KEY,快速顯示對應的值
- KEY 支持「點語法」和列表下標:
nameuser.nameitems.0.id
- 界面要盡量簡潔,美觀,適合日常調(diào)試 JSON 時快速使用
最終效果:
- 頂部標題 + 提示語,說明工具用途和操作方式
- 中間一行顯示當前 JSON 文件路徑 + 打開按鈕
- 一行 KEY 輸入 + 查詢按鈕
- 下方大區(qū)域顯示查詢結(jié)果(支持格式化 JSON)
- 底部狀態(tài)欄顯示操作結(jié)果提示(成功 / 失?。?/li>
二、項目結(jié)構(gòu)與入口
本工具的主體代碼全部在一個文件中:
- 主文件:
main.py - 主類:
JsonViewer(QMainWindow) - 入口函數(shù):
main()
入口函數(shù)代碼:
def main():
app = QApplication(sys.argv)
viewer = JsonViewer()
viewer.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
這是典型的 PyQt5 應用啟動方式:
- 創(chuàng)建
QApplication實例 - 實例化主窗口
JsonViewer - 顯示窗口
- 進入事件循環(huán)
三、窗口與整體樣式設計
1. 主窗口類與基礎(chǔ)設置
主窗口繼承自 QMainWindow:
class JsonViewer(QMainWindow):
def __init__(self):
super().__init__()
self.data = None
self.current_path = None
self.init_ui()
self.data:用來保存當前加載的 JSON 對象self.current_path:記錄當前 JSON 文件路徑init_ui():負責創(chuàng)建和布局所有控件,并設置樣式
2. 設置窗口大小與全局樣式
def init_ui(self):
self.setWindowTitle("JSON快速查看器")
self.resize(800, 520)
self.setStyleSheet(
"""
QWidget {
background-color: #f5f5f7;
font-family: "Microsoft YaHei";
font-size: 10pt;
}
QPushButton {
background-color: #0078d7;
color: white;
border-radius: 4px;
padding: 6px 14px;
}
QPushButton:hover {
background-color: #0a84ff;
}
QPushButton:pressed {
background-color: #005a9e;
}
QLineEdit, QTextEdit {
background-color: #ffffff;
border: 1px solid #d0d0d5;
border-radius: 4px;
}
QLineEdit:focus, QTextEdit:focus {
border: 1px solid #0a84ff;
}
"""
)
這里用了一段簡單的 Qt 樣式表(類似 CSS):
- 全局字體:微軟雅黑 10pt
- 背景色:淡灰色
#f5f5f7 - 按鈕:藍色背景 + 白字 + 圓角 + 懸停 / 按下態(tài)
- 輸入框和文本框:白色背景 + 邊框 + 聚焦時高亮
通過一次性設置 QWidget 和各控件的樣式,可以避免對每個控件逐個設置屬性,代碼更簡潔,視覺也更統(tǒng)一。
四、布局與控件拆解
1. 主布局與標題區(qū)
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QVBoxLayout()
central_widget.setLayout(main_layout)
main_layout.setContentsMargins(20, 18, 20, 18)
main_layout.setSpacing(12)
self.info_label = QLabel("JSON 快速查看器")
self.info_label.setAlignment(Qt.AlignCenter)
title_font = self.info_label.font()
title_font.setPointSize(14)
title_font.setBold(True)
self.info_label.setFont(title_font)
main_layout.addWidget(self.info_label)
subtitle = QLabel("拖入 JSON 文件到窗口,或點擊右側(cè)按鈕選擇文件")
subtitle.setAlignment(Qt.AlignCenter)
subtitle.setStyleSheet("color: #666666;")
main_layout.addWidget(subtitle)
- 縱向布局
QVBoxLayout:從上到下堆疊各個區(qū)域 - 主標題用 14 號加粗字體,居中顯示
- 副標題用淺灰色,提示使用方法
2. 文件選擇行(顯示路徑 + 打開按鈕)
file_layout = QHBoxLayout()
self.file_label = QLabel("未選擇文件")
self.file_label.setMinimumWidth(300)
self.file_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
self.file_label.setStyleSheet("color: #555555;")
open_button = QPushButton("打開JSON")
open_button.clicked.connect(self.open_file)
file_layout.addWidget(self.file_label)
file_layout.addWidget(open_button)
main_layout.addLayout(file_layout)
設計要點:
- 使用水平布局
QHBoxLayout,左邊是文件路徑,右邊是按鈕 - 文件路徑標簽支持鼠標選中,方便復制路徑
- 初始提示為「未選擇文件」
3. KEY 輸入行(KEY + 輸入框 + 查詢按鈕)
key_layout = QHBoxLayout()
key_label = QLabel("KEY:")
key_label.setStyleSheet("color: #333333;")
self.key_edit = QLineEdit()
self.key_edit.setPlaceholderText("例如: user.name 或 items.0.id")
key_font = self.key_edit.font()
key_font.setPointSize(10)
self.key_edit.setFont(key_font)
search_button = QPushButton("查詢")
search_button.clicked.connect(self.lookup_key)
self.key_edit.returnPressed.connect(self.lookup_key)
key_layout.addWidget(key_label)
key_layout.addWidget(self.key_edit)
key_layout.addWidget(search_button)
main_layout.addLayout(key_layout)
細節(jié)設計:
- 提示語直接告訴用戶 KEY 的寫法示例
- 支持兩種觸發(fā)方式:
- 點擊「查詢」按鈕
- 在輸入框里按 Enter(
returnPressed信號)
4. 結(jié)果顯示區(qū)與狀態(tài)欄
self.result_edit = QTextEdit()
self.result_edit.setReadOnly(True)
result_font = self.result_edit.font()
result_font.setFamily("Consolas")
result_font.setPointSize(10)
self.result_edit.setFont(result_font)
main_layout.addWidget(self.result_edit)
self.status_label = QLabel("")
self.status_label.setStyleSheet("color: #2e7d32;")
main_layout.addWidget(self.status_label)
- 結(jié)果用
QTextEdit展示,適合顯示多行 JSON - 使用等寬字體
Consolas,方便對齊與閱讀 - 底部
status_label用來顯示提示信息:- JSON 加載成功
- 未找到對應的值
- 請先加載 JSON 文件
等等
五、拖拽與打開 JSON 文件
1. 開啟拖拽支持
self.setAcceptDrops(True)
然后重寫兩個事件函數(shù):
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
for url in event.mimeData().urls():
path = url.toLocalFile()
if path.lower().endswith(".json"):
event.acceptProposedAction()
return
event.ignore()
邏輯:
- 拖入的內(nèi)容如果包含文件 URL
- 且其中有
.json后綴的文件 - 則接受這次拖拽,否則忽略
真正的放下事件:
def dropEvent(self, event):
for url in event.mimeData().urls():
path = url.toLocalFile()
if path.lower().endswith(".json"):
self.load_json(path)
break
- 取第一個
.json文件的路徑 - 調(diào)用
load_json進行加載
2. 通過文件選擇框打開 JSON
def open_file(self):
path, _ = QFileDialog.getOpenFileName(
self,
"選擇 JSON 文件",
"",
"JSON Files (*.json);;All Files (*)",
)
if path:
self.load_json(path)
使用 QFileDialog.getOpenFileName:
- 默認過濾器是
.json文件 - 也可以切換為「所有文件」打開
3. 加載 JSON 文件
def load_json(self, path):
try:
with open(path, "r", encoding="utf-8") as f:
self.data = json.load(f)
self.current_path = path
self.file_label.setText(path)
self.status_label.setText("JSON 加載成功")
self.result_edit.clear()
except Exception as e:
self.data = None
self.current_path = None
self.file_label.setText("未選擇文件")
self.status_label.setText("加載失敗: {0}".format(e))
self.result_edit.clear()
- 成功:
json.load解析為 Python 對象(dict / list)- 更新當前路徑顯示
- 清空結(jié)果區(qū)域
- 狀態(tài)顯示為「JSON 加載成功」
- 失敗:
- 清空狀態(tài)
- 文件標簽重置
- 狀態(tài)欄顯示錯誤原因
六、KEY 路徑解析與查詢邏輯
1. 查詢?nèi)肟诤瘮?shù)
def lookup_key(self):
if self.data is None:
self.status_label.setText("請先加載 JSON 文件")
return
key_path = self.key_edit.text().strip()
if not key_path:
self.status_label.setText("請輸入 KEY")
return
try:
value = self.get_value_by_path(self.data, key_path)
except (KeyError, IndexError, TypeError):
self.status_label.setText("未找到對應的值")
self.result_edit.clear()
return
if isinstance(value, (dict, list)):
text = json.dumps(value, ensure_ascii=False, indent=2)
else:
text = str(value)
self.result_edit.setPlainText(text)
self.status_label.setText("查詢成功")
邏輯分幾步:
- 檢查是否已加載 JSON
- 檢查 KEY 是否為空
- 調(diào)用
get_value_by_path獲取值,捕獲各種失敗情況 - 如果結(jié)果是
dict或list,用json.dumps美化輸出 - 否則直接轉(zhuǎn)成字符串顯示
2. 路徑解析核心函數(shù)
def get_value_by_path(self, data, path):
if not path:
return data
current = data
parts = path.split(".")
for part in parts:
if isinstance(current, list) and part.isdigit():
index = int(part)
current = current[index]
elif isinstance(current, dict):
if part in current:
current = current[part]
else:
raise KeyError(part)
else:
raise KeyError(part)
return current
這個函數(shù)支持的語法:
- 對象鍵:
user.name會依次訪問data["user"]["name"]
- 列表下標:
items.0相當于data["items"][0]items.0.id相當于data["items"][0]["id"]
實現(xiàn)方式:
- 把路徑按
.切分為列表["items", "0", "id"] - 從根對象開始,逐層向下走
- 當前對象是 list 且當前 part 是數(shù)字時:
- 解析成 int 下標,訪問對應元素
- 當前對象是 dict 時:
- 直接按照鍵訪問
- 如果中途類型不匹配或鍵不存在,就拋異常,由調(diào)用方統(tǒng)一處理為「未找到對應的值」
這個函數(shù)邏輯簡單清晰,但已經(jīng)覆蓋了絕大部分日常 JSON 調(diào)試的需求。
七、少量代碼實現(xiàn)一個高頻小工具
整個 main.py 代碼量不大,卻完成了:
- 一個小而美的 PyQt5 窗口應用
- 支持拖拽 / 打開 JSON 文件
- 支持 KEY 路徑解析(對象 + 列表)
- 自適應格式化輸出結(jié)果
- 簡單但實用的狀態(tài)提示和 UI 美化
如果需要擴展,這個工具還可以進一步完善:
- 支持
a[0].b這種帶中括號的路徑語法 - 增加「歷史 KEY」下拉列表,快速重復查詢
- 添加「復制結(jié)果」按鈕,一鍵復制查詢結(jié)果
- 增加「JSON 樹形視圖」,可視化瀏覽整個結(jié)構(gòu)
八、小結(jié)
這篇文章從需求出發(fā),完整拆解了 main.py 中的實現(xiàn):
- 如何用 PyQt5 快速搭建一個桌面小工具
- 如何用樣式表和字體調(diào)整讓界面更友好
- 如何通過拖拽和文件選擇加載 JSON
- 如何用簡單的「點語法 + 數(shù)字下標」解析 JSON 路徑
如果你也經(jīng)常需要調(diào)試接口或查看復雜 JSON,不妨參考這個實現(xiàn),按自己的習慣繼續(xù)擴展,讓它成為你日常開發(fā)中的一個趁手小工具。
以上就是Python使用PyQt5打造一個JSON快速查看器的詳細內(nèi)容,更多關(guān)于PyQt5 JSON快速查看器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python調(diào)用百度api實現(xiàn)語音識別詳解
這篇文章主要介紹了Python通過調(diào)用百度api實現(xiàn)語音識別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2021-12-12
Python使用PaddleOCR實現(xiàn)PDF/圖片文字識別與版面還原
本文介紹了如何利用 PaddleOCR 實現(xiàn)對 PDF 文件或圖片 的文字識別,并在識別后將文本內(nèi)容按照 原始版面位置 進行還原重建,感興趣的小伙伴可以了解下2025-11-11
scrapy自定義pipeline類實現(xiàn)將采集數(shù)據(jù)保存到mongodb的方法
這篇文章主要介紹了scrapy自定義pipeline類實現(xiàn)將采集數(shù)據(jù)保存到mongodb的方法,涉及scrapy采集及操作mongodb數(shù)據(jù)庫的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-04-04
Python使用內(nèi)置函數(shù)setattr設置對象的屬性值
這篇文章主要介紹了Python使用內(nèi)置函數(shù)setattr設置對象的屬性值,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10
idea2020手動安裝python插件的實現(xiàn)方法
這篇文章主要介紹了idea2020手動安裝python插件的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07
關(guān)于pip安裝opencv-python遇到的問題
這篇文章主要介紹了關(guān)于pip安裝opencv-python遇到的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02

