Python | 1 日 120 分 × 7 日アプリ学習:JSON保存アプリ(中級編)

Web APP Python
スポンサーリンク

7日目のゴール

7日目のテーマは
「JSON保存アプリを“完成形”にまとめる」
つまり、6日間で学んだすべてを統合して
ひとつのアプリとして成立する形に仕上げること です。

ここまでであなたはすでに、

JSON の読み書き
複数データの保存
検索・更新・削除
フィルタ・ソート
データ構造の拡張

といった、アプリ開発に必要な基礎をすべて習得しています。

7日目では、それらをまとめて
「実用的な ToDo JSON アプリ」 を完成させます。


JSON保存アプリの完成形を考える

どんなアプリに仕上げるのか

7日目の完成形は、次のようなアプリです。

タスクを追加できる
タスクに優先度・締切日・メモを持たせられる
完了状態を変更できる
タスクを削除できる
完了・未完了で絞り込める
キーワード検索ができる
優先度順・締切日順に並べ替えられる
JSON に保存され、次回起動時に復元される

つまり、
「小さなタスク管理アプリ」として十分使えるレベル
まで仕上げます。


アプリの構造をもう一度整理する

役割を3つに分けるのが最強

アプリは次の3つの役割で構成します。

データ管理(JSON の読み書き)
データ操作(追加・検索・更新・削除・フィルタ・ソート)
アプリの流れ(メニュー・入力・表示)

この構造を守ることで、

コードが読みやすい
修正しやすい
機能追加しやすい

という「強いアプリ」になります。


完成版:JSON保存 ToDo アプリ(フル機能)

すべての機能を統合したコード

import json
import os

FILENAME = "tasks.json"

def load_tasks():
    if not os.path.exists(FILENAME):
        return []
    with open(FILENAME, "r", encoding="utf-8") as f:
        return json.load(f)

def save_tasks(tasks):
    with open(FILENAME, "w", encoding="utf-8") as f:
        json.dump(tasks, f, ensure_ascii=False, indent=2)

def add_task(tasks):
    title = input("タスク名: ")
    priority = input("優先度(high / normal / low): ")
    due = input("締切日(例: 2025-05-10。未設定なら空のまま): ")
    memo = input("メモ(任意): ")

    if priority not in ("high", "normal", "low"):
        print("優先度が不正です。normal として扱います。")
        priority = "normal"

    if due == "":
        due = None
    if memo == "":
        memo = None

    task = {
        "title": title,
        "priority": priority,
        "due": due,
        "memo": memo,
        "done": False
    }

    tasks.append(task)
    print("タスクを追加しました。")

def find_task(tasks, title):
    for task in tasks:
        if task["title"] == title:
            return task
    return None

def update_task_done(tasks):
    title = input("完了状態を変更するタスク名: ")
    task = find_task(tasks, title)
    if task is None:
        print("タスクが見つかりません。")
        return

    done_text = input("完了なら1、未完了なら0: ")
    task["done"] = (done_text == "1")
    print("完了状態を更新しました。")

def delete_task(tasks):
    title = input("削除するタスク名: ")
    for i, task in enumerate(tasks):
        if task["title"] == title:
            del tasks[i]
            print("削除しました。")
            return
    print("タスクが見つかりません。")

def filter_done_tasks(tasks):
    return [task for task in tasks if task["done"]]

def filter_undone_tasks(tasks):
    return [task for task in tasks if not task["done"]]

def search_tasks_by_keyword(tasks, keyword):
    return [task for task in tasks if keyword in task["title"]]

def sort_tasks_by_priority(tasks):
    def priority_value(task):
        p = task.get("priority", "normal")
        if p == "high":
            return 0
        elif p == "normal":
            return 1
        else:
            return 2
    return sorted(tasks, key=priority_value)

def sort_tasks_by_due(tasks):
    def due_value(task):
        due = task.get("due")
        if due is None:
            return "9999-12-31"
        return due
    return sorted(tasks, key=due_value)

def show_tasks(tasks):
    if not tasks:
        print("タスクはありません。")
        return

    print("=== タスク一覧 ===")
    for task in tasks:
        mark = "✔" if task["done"] else "✗"

        p = task.get("priority")
        if p == "high":
            priority_label = "[高]"
        elif p == "low":
            priority_label = "[低]"
        else:
            priority_label = "[中]"

        due = task.get("due")
        if due is None:
            due_label = "(締切: なし)"
        else:
            due_label = f"(締切: {due})"

        memo = task.get("memo")
        if memo:
            memo_label = f" - メモ: {memo}"
        else:
            memo_label = ""

        print(f"{mark} {priority_label} {task['title']} {due_label}{memo_label}")

def main():
    tasks = load_tasks()
    print("JSONファイルから読み込みました。")

    while True:
        print("\n=== メニュー ===")
        print("1: タスク追加")
        print("2: 全タスク表示")
        print("3: 完了タスクだけ表示")
        print("4: 未完了タスクだけ表示")
        print("5: キーワード検索")
        print("6: 優先度順で表示")
        print("7: 締切日順で表示")
        print("8: 完了状態を変更")
        print("9: タスク削除")
        print("0: 終了")

        choice = input("番号を選んでください: ")

        if choice == "1":
            add_task(tasks)
            save_tasks(tasks)

        elif choice == "2":
            show_tasks(tasks)

        elif choice == "3":
            show_tasks(filter_done_tasks(tasks))

        elif choice == "4":
            show_tasks(filter_undone_tasks(tasks))

        elif choice == "5":
            keyword = input("キーワード: ")
            show_tasks(search_tasks_by_keyword(tasks, keyword))

        elif choice == "6":
            show_tasks(sort_tasks_by_priority(tasks))

        elif choice == "7":
            show_tasks(sort_tasks_by_due(tasks))

        elif choice == "8":
            update_task_done(tasks)
            save_tasks(tasks)

        elif choice == "9":
            delete_task(tasks)
            save_tasks(tasks)

        elif choice == "0":
            save_tasks(tasks)
            print("終了します。")
            break

        else:
            print("正しい番号を入力してください。")

if __name__ == "__main__":
    main()
Python

7日目で絶対に押さえてほしい本質

JSON保存アプリは「データ構造 × 操作 × 表示」でできている

今日のまとめとして、
JSON保存アプリの本質を整理します。

データ構造をどう設計するか
データをどう操作するか
操作結果をどう見せるか

この三つを分けて考えることで、
アプリは驚くほど作りやすくなります。

そして JSON は、

Python の dict / list をそのまま保存できる
人間にも読みやすい
アプリの「状態」を丸ごと保存できる

という、アプリ開発に最適な形式です。

あなたは7日間で、
「JSONを使ってアプリのデータを扱う力」 を完全に身につけました。


ここから先に進むためのヒント

次のステップは「永続化の応用」

もしさらに進みたいなら、こんな方向があります。

タスクにタグをつける
サブタスクを持たせる(入れ子構造)
データを複数ファイルに分ける
クラスを使ってタスクをオブジェクトとして扱う
GUI(Tkinter)で画面をつける
Webアプリ(Flask / FastAPI)にする

どれも JSON の知識がそのまま活きます。

タイトルとURLをコピーしました