import sqlite3 import json import tkinter as tk from tkinter import ttk, filedialog, messagebox from datetime import datetime class SQLiteToJSONConverter: def __init__(self, root): self.root = root self.root.title("SQLite 表转 JSON 工具") self.root.geometry("800x600") # 变量 self.db_path = tk.StringVar() self.tables = [] self.selected_table = tk.StringVar() self.create_widgets() def create_widgets(self): # 主框架 main_frame = ttk.Frame(self.root, padding="10") main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) # 数据库选择部分 db_frame = ttk.LabelFrame(main_frame, text="数据库选择", padding="5") db_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5) ttk.Entry(db_frame, textvariable=self.db_path, width=70).grid( row=0, column=0, padx=5 ) ttk.Button(db_frame, text="浏览", command=self.browse_db).grid( row=0, column=1, padx=5 ) ttk.Button(db_frame, text="连接", command=self.connect_db).grid( row=0, column=2, padx=5 ) # 表选择部分 table_frame = ttk.LabelFrame(main_frame, text="表选择", padding="5") table_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5) ttk.Label(table_frame, text="选择表:").grid(row=0, column=0, sticky=tk.W) self.table_combo = ttk.Combobox( table_frame, textvariable=self.selected_table, state="readonly" ) self.table_combo.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=5) ttk.Button(table_frame, text="加载数据", command=self.load_table_data).grid( row=0, column=2, padx=5 ) # 数据显示部分 data_frame = ttk.LabelFrame(main_frame, text="表数据", padding="5") data_frame.grid( row=2, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=5 ) # 创建Treeview显示数据 columns = ("#0",) self.tree = ttk.Treeview(data_frame, columns=columns, show="headings") vsb = ttk.Scrollbar(data_frame, orient="vertical", command=self.tree.yview) hsb = ttk.Scrollbar(data_frame, orient="horizontal", command=self.tree.xview) self.tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set) self.tree.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) vsb.grid(row=0, column=1, sticky=(tk.N, tk.S)) hsb.grid(row=1, column=0, sticky=(tk.W, tk.E)) # 按钮部分 button_frame = ttk.Frame(main_frame) button_frame.grid(row=3, column=0, columnspan=2, pady=10) ttk.Button(button_frame, text="导出为JSON", command=self.export_to_json).pack( side=tk.LEFT, padx=5 ) ttk.Button(button_frame, text="清空", command=self.clear_all).pack( side=tk.LEFT, padx=5 ) ttk.Button(button_frame, text="退出", command=self.root.quit).pack( side=tk.LEFT, padx=5 ) # 配置权重 self.root.columnconfigure(0, weight=1) self.root.rowconfigure(0, weight=1) main_frame.columnconfigure(0, weight=1) main_frame.rowconfigure(2, weight=1) data_frame.columnconfigure(0, weight=1) data_frame.rowconfigure(0, weight=1) def browse_db(self): file_path = filedialog.askopenfilename( title="选择SQLite数据库文件", filetypes=[ ("SQLite数据库", "*.db *.sqlite *.sqlite3"), ("所有文件", "*.*"), ], ) if file_path: self.db_path.set(file_path) def connect_db(self): if not self.db_path.get(): messagebox.showerror("错误", "请先选择数据库文件") return try: conn = sqlite3.connect(self.db_path.get()) cursor = conn.cursor() # 获取所有表名 cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") self.tables = [table[0] for table in cursor.fetchall()] self.table_combo["values"] = self.tables if self.tables: self.selected_table.set(self.tables[0]) conn.close() messagebox.showinfo( "成功", f"成功连接到数据库,找到 {len(self.tables)} 个表" ) except sqlite3.Error as e: messagebox.showerror("数据库错误", f"连接数据库时出错: {str(e)}") def load_table_data(self): if not self.selected_table.get(): messagebox.showerror("错误", "请先选择表") return try: conn = sqlite3.connect(self.db_path.get()) conn.row_factory = sqlite3.Row # 这样可以使用列名访问数据 cursor = conn.cursor() # 获取表数据 cursor.execute(f"SELECT * FROM {self.selected_table.get()}") rows = cursor.fetchall() # 清空Treeview for item in self.tree.get_children(): self.tree.delete(item) # 设置列 columns = [description[0] for description in cursor.description] self.tree["columns"] = columns for col in columns: self.tree.heading(col, text=col) self.tree.column(col, width=100, minwidth=50) # 添加数据 for row in rows: self.tree.insert("", "end", values=tuple(row)) conn.close() except sqlite3.Error as e: messagebox.showerror("数据库错误", f"加载数据时出错: {str(e)}") def export_to_json(self): if not self.selected_table.get(): messagebox.showerror("错误", "请先选择表") return # 选择保存位置 file_path = filedialog.asksaveasfilename( title="保存JSON文件", defaultextension=".json", filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")], ) if not file_path: return try: conn = sqlite3.connect(self.db_path.get()) conn.row_factory = sqlite3.Row # 使用列名访问数据 cursor = conn.cursor() # 获取表数据 cursor.execute(f"SELECT * FROM {self.selected_table.get()}") rows = cursor.fetchall() # 转换为字典列表 result = [dict(row) for row in rows] # 写入JSON文件 with open(file_path, "w", encoding="utf-8") as f: json.dump(result, f, indent=4, ensure_ascii=False) conn.close() messagebox.showinfo("成功", f"数据已成功导出到 {file_path}") except sqlite3.Error as e: messagebox.showerror("数据库错误", f"导出数据时出错: {str(e)}") except Exception as e: messagebox.showerror("错误", f"保存文件时出错: {str(e)}") def clear_all(self): self.db_path.set("") self.tables = [] self.table_combo["values"] = [] self.selected_table.set("") for item in self.tree.get_children(): self.tree.delete(item) self.tree["columns"] = ("#0",) if __name__ == "__main__": root = tk.Tk() app = SQLiteToJSONConverter(root) root.mainloop()