Update json_student_dal.py

master
ptuaqkmj6 2 months ago
parent 8fc3101052
commit 6ddcb003d5

@ -6,126 +6,181 @@ from datetime import datetime
class JsonStudentDAL(IStudentDAL):
"""学生信息的JSON文件存储实现"""
"""学生信息的JSON文件存储实现实现了IStudentDAL接口提供基于JSON文件的学生数据增删改查功能"""
def __init__(self, file_path: str = 'students.json'):
"""初始化JSON数据访问层
:param file_path: JSON数据文件路径默认使用当前目录下的students.json"""
self.file_path = file_path
self._ensure_file_exists()
self._ensure_file_exists() # 调用私有方法确保数据文件存在,避免后续操作报错
def _ensure_file_exists(self):
"""确保JSON文件存在"""
"""确保JSON数据文件存在且格式正确
处理两种异常情况
1. 文件不存在时创建空JSON数组文件
2. 文件存在但非JSON格式时如损坏重建空文件"""
try:
with open(self.file_path, 'r', encoding='utf-8') as file:
json.load(file)
json.load(file) # 尝试解析文件验证是否为合法JSON
except (FileNotFoundError, json.JSONDecodeError):
# 异常处理:文件不存在或解析失败时,创建包含空数组的新文件
with open(self.file_path, 'w', encoding='utf-8') as file:
json.dump([], file)
json.dump([], file) # 写入空数组,确保文件格式正确
def _student_to_dict(self, student: Student) -> dict:
"""将Student对象转换为字典"""
"""将Student实体对象转换为JSON兼容的字典格式
:param student: 学生实体对象
:return: 可序列化的字典日期类型转换为字符串
处理逻辑
- 日期字段enrollment_date转为%Y-%m-%d格式字符串
- None值保持为None确保JSON序列化合法"""
return {
'name': student.name,
'id_card': student.id_card,
'stu_id': student.stu_id,
'gender': student.gender,
'height': student.height,
'weight': student.weight,
'name': student.name, # 直接存储字符串属性
'id_card': student.id_card, # 身份证号(字符串)
'stu_id': student.stu_id, # 学号(字符串)
'gender': student.gender, # 性别(布尔值)
'height': student.height, # 身高(整数)
'weight': student.weight, # 体重(整数)
# 日期转字符串:若存在日期则格式化为%Y-%m-%d否则保持None
'enrollment_date': str(student.enrollment_date) if student.enrollment_date else None,
'class_name': student.class_name,
'major': student.major,
'email': student.email,
'phone': student.phone
'class_name': student.class_name, # 班级(字符串)
'major': student.major, # 专业(字符串)
'email': student.email, # 邮箱(字符串)
'phone': student.phone # 电话(字符串)
}
def _dict_to_student(self, data: dict) -> Student:
"""将字典转换为Student对象"""
# 处理日期类型
"""将JSON字典转换为Student实体对象
:param data: 从JSON文件读取的字典数据
:return: 初始化的Student对象字符串日期转换为date对象
处理逻辑
- enrollment_date字段从字符串解析为datetime.date对象
- 缺失字段使用None或默认值初始化"""
enrollment_date = data.get('enrollment_date')
if enrollment_date:
# 字符串转日期使用strptime解析为datetime对象再提取date部分
enrollment_date = datetime.strptime(enrollment_date, '%Y-%m-%d').date()
return Student(
name=data.get('name'),
id_card=data.get('id_card'),
stu_id=data.get('stu_id'),
gender=data.get('gender'),
height=data.get('height'),
weight=data.get('weight'),
enrollment_date=enrollment_date,
class_name=data.get('class_name'),
major=data.get('major'),
email=data.get('email'),
phone=data.get('phone')
name=data.get('name'), # 获取姓名缺失时为None
id_card=data.get('id_card'), # 获取身份证号
stu_id=data.get('stu_id'), # 获取学号
gender=data.get('gender'), # 获取性别
height=data.get('height'), # 获取身高
weight=data.get('weight'), # 获取体重
enrollment_date=enrollment_date, # 转换后的入学日期
class_name=data.get('class_name'), # 获取班级
major=data.get('major'), # 获取专业
email=data.get('email'), # 获取邮箱
phone=data.get('phone') # 获取电话
)
def _load_data(self) -> List[dict]:
"""加载JSON文件数据"""
"""从JSON文件加载学生数据
:return: 包含学生字典的列表
封装文件读取逻辑统一处理编码和JSON解析"""
with open(self.file_path, 'r', encoding='utf-8') as file:
return json.load(file)
return json.load(file) # 读取文件并解析为Python列表
def _save_data(self, data: List[dict]):
"""保存数据到JSON文件"""
"""将学生数据保存至JSON文件
:param data: 包含学生字典的列表
保存逻辑
- ensure_ascii=False确保中文正常存储
- indent=2添加缩进提升文件可读性"""
with open(self.file_path, 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=2)
json.dump(data, file, ensure_ascii=False, indent=2) # 写入文件禁用ASCII转义
def get_by_id(self, id_card: str) -> Optional[Student]:
"""根据身份证号获取学生信息"""
"""根据身份证号查询学生信息
:param id_card: 待查询的身份证号
:return: 匹配的Student对象或None
实现逻辑
- 加载全部数据遍历匹配
- 找到后转换为Student对象返回"""
for data in self._load_data():
if data.get('id_card') == id_card:
return self._dict_to_student(data)
return None
if data.get('id_card') == id_card: # 精确匹配身份证号
return self._dict_to_student(data) # 转换为实体对象
return None # 未找到返回None
def get_by_stu_id(self, stu_id: str) -> Optional[Student]:
"""根据学号获取学生信息"""
"""根据学号查询学生信息逻辑同get_by_id
:param stu_id: 待查询的学号
:return: 匹配的Student对象或None"""
for data in self._load_data():
if data.get('stu_id') == stu_id:
if data.get('stu_id') == stu_id: # 精确匹配学号
return self._dict_to_student(data)
return None
def get_all(self) -> List[Student]:
"""获取所有学生信息"""
return [self._dict_to_student(data) for data in self._load_data()]
"""获取所有学生信息
:return: 包含所有Student对象的列表
实现逻辑
- 加载全部字典数据
- 逐个转换为Student对象"""
return [self._dict_to_student(data) for data in self._load_data()] # 列表推导式批量转换
def add(self, student: Student) -> bool:
"""添加学生信息"""
# 检查学号和身份证号是否已存在
"""添加新学生信息
:param student: 待添加的Student对象
:return: 添加成功返回True失败返回False
业务逻辑
1. 先校验身份证号和学号的唯一性
2. 校验通过后追加数据并保存
3. 唯一性冲突时返回False"""
# 检查身份证号或学号是否已存在
if self.get_by_id(student.id_card) or self.get_by_stu_id(student.stu_id):
return False
return False # 已存在相同标识,添加失败
data = self._load_data()
data.append(self._student_to_dict(student))
self._save_data(data)
return True
data = self._load_data() # 加载当前数据
data.append(self._student_to_dict(student)) # 转换并追加
self._save_data(data) # 保存更新后的数据
return True # 添加成功
def update(self, student: Student) -> bool:
"""更新学生信息"""
data = self._load_data()
updated = False
"""更新学生信息
:param student: 包含更新后信息的Student对象
:return: 更新成功返回True失败返回False
实现逻辑
1. 按身份证号定位记录
2. 找到后替换为新数据
3. 未找到或无变更时返回False"""
data = self._load_data() # 加载当前数据
updated = False # 标记是否更新
for i, item in enumerate(data):
if item.get('id_card') == student.id_card:
data[i] = self._student_to_dict(student)
if item.get('id_card') == student.id_card: # 匹配身份证号
data[i] = self._student_to_dict(student) # 替换为新数据
updated = True
break
if updated:
self._save_data(data)
return updated
self._save_data(data) # 保存更新后的数据
return updated # 返回是否更新成功
def delete_by_id(self, id_card: str) -> bool:
"""根据身份证号删除学生信息"""
data = self._load_data()
original_length = len(data)
"""根据身份证号删除学生信息
:param id_card: 待删除学生的身份证号
:return: 删除成功返回True失败返回False
实现逻辑
1. 过滤掉目标身份证号的记录
2. 比较删除前后数据长度
3. 长度变化时保存并返回True"""
data = self._load_data() # 加载当前数据
original_length = len(data) # 记录原始长度
# 过滤掉目标身份证号的记录
data = [item for item in data if item.get('id_card') != id_card]
if len(data) < original_length:
self._save_data(data)
if len(data) < original_length: # 长度减少表示删除成功
self._save_data(data) # 保存更新后的数据
return True
return False
return False # 未找到目标记录
def delete_by_stu_id(self, stu_id: str) -> bool:
"""根据学号删除学生信息"""
"""根据学号删除学生信息逻辑同delete_by_id
:param stu_id: 待删除学生的学号
:return: 删除成功返回True失败返回False"""
data = self._load_data()
original_length = len(data)
@ -137,14 +192,35 @@ class JsonStudentDAL(IStudentDAL):
return False
def search_by_name(self, name: str) -> List[Student]:
"""根据姓名模糊查询学生信息"""
return [self._dict_to_student(data) for data in self._load_data() if name in data.get('name', '')]
"""根据姓名模糊查询学生
:param name: 待查询的姓名片段
:return: 包含匹配学生的列表
实现逻辑
- 遍历所有数据
- 使用in操作符实现包含匹配
- 处理name字段为None的情况"""
return [
self._dict_to_student(data) for data in self._load_data()
if name in data.get('name', '') # data.get('name', '')避免KeyError空字符串确保in操作合法
]
def search_by_class(self, class_name: str) -> List[Student]:
"""根据班级模糊查询学生信息"""
return [self._dict_to_student(data) for data in self._load_data() if
class_name in (data.get('class_name') or '')]
"""根据班级模糊查询学生
:param class_name: 待查询的班级片段
:return: 包含匹配学生的列表
实现逻辑
- 处理class_name为None的情况替换为空字符串
- 使用in操作符实现包含匹配"""
return [
self._dict_to_student(data) for data in self._load_data()
if class_name in (data.get('class_name') or '') # data.get('class_name')为None时替换为空字符串
]
def search_by_major(self, major: str) -> List[Student]:
"""根据专业模糊查询学生信息"""
return [self._dict_to_student(data) for data in self._load_data() if major in (data.get('major') or '')]
"""根据专业模糊查询学生逻辑同search_by_class
:param major: 待查询的专业片段
:return: 包含匹配学生的列表"""
return [
self._dict_to_student(data) for data in self._load_data()
if major in (data.get('major') or '') # 处理major为None的情况
]

Loading…
Cancel
Save