You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python操作JSON实现图书馆系统图书增删改功能咨询

图书馆系统CRUD功能修复与实现指南

1. 新增图书功能修复

你当前新增逻辑的核心问题是使用a追加模式直接往文件末尾写入单个JSON对象,完全没有读取原有数组结构,自然会把新数据写到闭合方括号外侧,破坏JSON格式。
正确实现逻辑:

  • 先读取整个books.json文件,解析为Python列表对象
  • 将新构造的图书对象追加到列表末尾
  • 以覆盖写入模式打开文件,将更新后的完整列表重新序列化为格式化JSON写回
    修正后可直接运行的代码:
import json
import os

def addBook(self):
    print("Please fill in the following information:")
    author = input("Author: ")
    country = input("Country: ")
    image = input("Image Link: ")
    lang = input("Language: ")
    link = input("Link: ")
    # 增加输入校验,避免非数字输入导致程序崩溃
    while True:
        try:
            pages = int(input("Pages: "))
            break
        except ValueError:
            print("Invalid input, please enter a valid integer for pages!")
    title = input("Title: ")
    isbn = input("ISBN: ")
    while True:
        try:
            year = int(input("Year: "))
            break
        except ValueError:
            print("Invalid input, please enter a valid integer for year!")
    new_book = {
        "author": author,
        "country": country,
        "imageLink": image,
        "language": lang,
        "link": link,
        "pages": pages,
        "title": title,
        "ISBN": isbn,
        "year": year
    }
    # 读取原有图书数据
    with open("books.json", "r", encoding="utf-8") as f:
        book_list = json.load(f)
    # 追加新图书到列表
    book_list.append(new_book)
    # 全量写回文件
    with open("books.json", "w", encoding="utf-8") as f:
        json.dump(book_list, f, indent=2, ensure_ascii=False)
    print("Book added successfully!")

补充说明:写文件时指定indent=2可以保持JSON格式化易读,ensure_ascii=False避免非英文内容被转义为乱码。


2. 图书选择功能修复

你现有选择逻辑的两个明显问题:

  • 只打印了匹配序号,但没有存储序号和原数据的对应关系,用户输入序号后无法定位到具体图书
  • 同一本书如果同时匹配作者、书名关键词,会被重复打印两次
    修正思路:新增匹配结果列表,存储命中图书在原数据中的索引,用户输入合法序号后直接返回对应索引,供编辑、删除功能调用。
    修正后代码:
def selectCatalogue(self):
    os.system('cls')
    keyword = input("Please fill the author or title of the book in: ").casefold()
    match_results = [] # 存储匹配图书在原列表中的索引
    # 读取最新的图书数据,不依赖全局变量
    with open("books.json", "r", encoding="utf-8") as f:
        data = json.load(f)
    print("=== Search Results ===")
    for idx, book in enumerate(data):
        # 作者或书名任意一个命中就算匹配,避免重复打印
        if keyword in book['author'].casefold() or keyword in book['title'].casefold():
            current_num = len(match_results) + 1
            print(f'[{current_num}] Author: {book["author"]}')
            print(f'    Country: {book["country"]}') 
            print(f'    Image link: {book["imageLink"]}') 
            print(f'    Language: {book["language"]}')    
            print(f'    Link: {book["link"]}') 
            print(f'    Pages: {book["pages"]}') 
            print(f'    Title: {book["title"]}') 
            print(f'    ISBN: {book["ISBN"]}') 
            print(f'    Year: {book["year"]}') 
            print(' ')
            match_results.append(idx)
    if not match_results:
        print("No matching books found!")
        return None
    # 校验用户输入合法性
    while True:
        try:
            choice = int(input("Please enter the number of the book you want to select: "))
            if 1 <= choice <= len(match_results):
                # 返回选中图书在原数据列表中的索引
                return match_results[choice-1]
            else:
                print(f"Please enter a number between 1 and {len(match_results)}")
        except ValueError:
            print("Invalid input, please enter a valid number!")

3. 图书编辑功能修复

你现有编辑逻辑的错误点:

  • 没有获取选中图书的索引,直接对整个列表做字段赋值,逻辑完全不成立
  • 存在字段赋值笔误:修改页数时错误赋值给了author字段
  • ISBN是字符串类型,转成整数会丢失前导零、超出数值范围引发报错
  • 修改后没有将更新后的数据写回文件
    修正后代码:
def editBook(self):
    # 先获取选中图书的索引
    target_idx = self.selectCatalogue()
    if target_idx is None:
        print("No book selected, return to main menu")
        return
    print("=== Select Field to Edit ===")
    print('[1] Author')
    print('[2] Country') 
    print('[3] Image link') 
    print('[4] Language')    
    print('[5] Link') 
    print('[6] Pages') 
    print('[7] Title') 
    print('[8] ISBN')
    print('[9] Year')
    # 读取全量图书数据
    with open("books.json", "r", encoding="utf-8") as f:
        book_list = json.load(f)
    target_book = book_list[target_idx]
    # 选择要修改的字段
    while True:
        choice = input("Enter the field number: ")
        if choice == '1':
            target_book["author"] = input("Please enter the new author name: ")
            break
        elif choice == '2':
            target_book["country"] = input("Please enter the new country name: ")
            break
        elif choice == '3':
            target_book["imageLink"] = input("Please enter the new image link: ")
            break
        elif choice == '4':
            target_book["language"] = input("Please enter the new language: ")
            break
        elif choice == '5':
            target_book["link"] = input("Please enter the new link: ")
            break
        elif choice == '6':
            while True:
                try:
                    target_book["pages"] = int(input("Please enter the new number of pages: "))
                    break
                except ValueError:
                    print("Invalid input, please enter a valid number!")
            break
        elif choice == '7':
            target_book["title"] = input("Please enter the new title: ")
            break
        elif choice == '8':
            # ISBN保持字符串类型,不做整数转换
            target_book["ISBN"] = input("Please enter the new ISBN: ")
            break
        elif choice == '9':
            while True:
                try:
                    target_book["year"] = int(input("Please enter the new year: "))
                    break
                except ValueError:
                    print("Invalid input, please enter a valid number!")
            break
        else:
            print("Invalid choice, please enter a number between 1 and 9")
    # 将更新后的数据全量写回文件
    with open("books.json", "w", encoding="utf-8") as f:
        json.dump(book_list, f, indent=2, ensure_ascii=False)
    print("Book information updated successfully!")

4. 图书删除功能实现

删除逻辑和编辑逻辑高度一致:先选中目标图书,从列表中移除对应元素后全量写回文件即可,参考代码:

def deleteBook(self):
    target_idx = self.selectCatalogue()
    if target_idx is None:
        print("No book selected, return to main menu")
        return
    # 读取全量数据
    with open("books.json", "r", encoding="utf-8") as f:
        book_list = json.load(f)
    # 移除选中的图书
    deleted_book = book_list.pop(target_idx)
    # 写回更新后的数据
    with open("books.json", "w", encoding="utf-8") as f:
        json.dump(book_list, f, indent=2, ensure_ascii=False)
    print(f"Book '{deleted_book['title']}' has been deleted successfully!")

通用优化建议

  • 所有JSON文件读写操作统一指定encoding="utf-8",避免Windows系统默认GBK编码导致的乱码问题
  • 可以把JSON文件的读取、写入逻辑抽成公共工具函数,减少重复代码
  • 涉及文件写入操作时,建议先写临时文件再替换原文件,避免程序中途崩溃损坏原有数据
  • 对ISBN这类固定格式字段,可以增加格式校验,提升数据合法性

内容的提问来源于stack exchange,提问作者jb18

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 19:39:17