DevCN
菜单
全部文章快讯开发科技深度热点

Python 文件与 JSON:保存任务后读回并校验结构

将带中文标题的任务列表保存到 JSON 文件,再读取并校验列表、字段与字段类型,区分 JSON 语法正确和业务数据有效。


本节目标

将带中文标题的任务列表保存到 JSON 文件,再读取并校验列表、字段与字段类型,区分 JSON 语法正确和业务数据有效。

知识与使用场景

JSON 适合交换结构化数据,但能被解析不等于符合业务要求。本节只接受任务列表,每个元素必须是字典,title 必须是非空字符串,done 必须是布尔值。

读写文本文件时明确使用 UTF-8,避免不同电脑的默认编码产生差异。ensure_ascii=False 保留中文可读性,indent 让文件便于检查。它们改变展示方式,不负责消除无效字段或保证业务约束。

练习使用 TemporaryDirectory 生成独立目录,执行结束后自动清理,不覆盖已有文件。真正保存到项目目录时,可以把目标换成 Path('data/tasks.json') 并先创建父目录;同时要考虑备份、失败写入和多进程同时修改。

完整示例

import json
from pathlib import Path
from tempfile import TemporaryDirectory


def validate_tasks(data):
    if not isinstance(data, list):
        raise ValueError("根节点必须是列表")
    for item in data:
        if not isinstance(item, dict):
            raise ValueError("任务必须是对象")
        title = item.get("title")
        if not isinstance(title, str) or not title.strip():
            raise ValueError("标题必须是非空字符串")
        if not isinstance(item.get("done"), bool):
            raise ValueError("done必须是布尔值")
    return data


tasks = [{"title": "学习JSON", "done": False}]
with TemporaryDirectory() as directory:
    path = Path(directory) / "tasks.json"
    path.write_text(json.dumps(tasks, ensure_ascii=False, indent=2), encoding="utf-8")
    loaded = validate_tasks(json.loads(path.read_text(encoding="utf-8")))
    print(loaded[0]["title"])
    print(loaded == tasks)

预期结果

学习JSON
True

运行与逐步理解

示例先序列化再读回,True 说明这份简单任务数据在往返后保持一致。程序中的 False 会在 JSON 中写成 false,读取后再恢复成 Python 布尔对象,不能用字符串 "False" 来代替。

validate_tasks 在遍历前先检查根节点,再逐项检查字段。空列表在本例中合法,额外字段也会保留;这属于明确的宽松策略。如果接入网站时要求只允许固定字段,可进一步拒绝多余键或构造只含允许字段的新字典。

JSON 解码失败会抛 JSONDecodeError,文件不存在会抛 FileNotFoundError。它们应在面向用户的调用层转换为不同提示,不能统统当成空任务列表,否则损坏文件可能被下一次保存覆盖。

常见问题与边界

  • bool('false') 得到 True,不能用它解析 JSON 字符串形式的布尔值。
  • JSON 对象键是字符串,不要依赖整数键往返后仍是整数。
  • write_text 会替换目标文件内容,正式持久化可先写临时文件再原子替换,并设计备份。
  • 本例适合小文件,read_text 加 json.loads 会把全文放入内存。

动手练习

分别验证 []、[{"title":"复习","done":"false"}] 和 {"tasks":[]},说明结果。

参考答案

空列表通过;done 是字符串的任务被拒绝;以字典作为根节点也被拒绝,即使它内部含 tasks 列表。本函数的入口契约是任务列表,需要提取正确节点后再验证。

DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。