Как устроена структура расписания в JSON

Расписание естественно описывается вложенными структурами: словарь верхнего уровня, где ключ — день недели, а значение — список пар на этот день. Каждая пара, в свою очередь, тоже словарь с полями номер, время, предмет, кабинет и преподаватель. Такая вложенность словарь внутри списка внутри словаря напрямую повторяет то, как выглядит расписание на бумаге, и её легко читать глазами прямо в файле, не запуская программу.

Пример записи одного дня выглядит примерно так: ключ понедельник указывает на список из нескольких словарей, и в каждом из них есть поле number со значением вроде 1, поле time со значением 8:30, поле subject со значением математика, поле room со значением 204 и поле teacher со значением фамилии учителя. Такой же список повторяется для каждого дня недели, а сама структура сверху остаётся одним словарём с семью ключами.

Почему JSON удобнее самодельного текстового формата

Первая волна самодельных форматов обычно выглядит как текстовый файл со строками через запятую или точку с запятой: понедельник, 1, 8:30, математика, 204. Формат ломается сразу, как только в названии предмета или в фамилии преподавателя встречается та же запятая — парсер режет строку не там, где нужно, и поле смещается. JSON решает эту проблему в корне: значения строк заключены в кавычки, а границы полей задаются структурой, а не случайным символом-разделителем, который легко встретить и внутри самих данных.

Вторая причина — самоописательность. Открыв текстовый файл с числами и запятыми через полгода, разработчик вынужден заново вспоминать, что означает третье поле в строке. В JSON каждое значение подписано именем ключа прямо рядом с собой, и файл читается без внешней документации. Третья причина практическая: формат поддержан стандартной библиотекой Python без единой внешней зависимости, тот же файл открывается в любом текстовом редакторе и легко расширяется новым полем без переписывания парсера.

Как прочитать файл в Python

Модуль json входит в стандартную библиотеку и не требует установки. Файл открывают функцией open с указанием кодировки utf-8 — без неё кириллица в названиях предметов рискует превратиться в набор случайных символов. Результат сразу передают в json.load, которая возвращает готовую структуру Python — вложенные словари и списки, с которыми можно работать сразу, без ручного разбора строк. Если данные пришли строкой, например по сети, а не лежат в файле на диске, вместо json.load используют json.loads, которая принимает строку напрямую.

Типичная ошибка при чтении

Частая ошибка новичка — забыть закрыть файл руками после чтения. Конструкция with open как контекстный менеджер решает это автоматически: файл закрывается сам, даже если внутри блока произошла ошибка. Вторая частая ошибка — открыть файл без явной кодировки на системе, где кодировка по умолчанию отличается от utf-8, тогда программа падает с ошибкой декодирования уже на первой кириллической букве в файле.

Как обращаться к полям расписания

После json.load переменная schedule ведёт себя как обычный словарь Python. Получить список пар на среду можно обращением schedule со средой в квадратных скобках, а конкретную пару из этого списка — по индексу, например нулевому элементу для первого урока дня. Дальше от словаря пары берут нужное поле тем же способом — по имени ключа subject, room или teacher. Перебор всех дней и всех пар внутри дня делают вложенным циклом for: внешний цикл идёт по ключам словаря дней, внутренний — по списку пар конкретного дня.

Как обработать отсутствующий ключ

Если в какой-то записи забыли указать кабинет, а код обращается к полю room напрямую через квадратные скобки, программа немедленно упадёт с исключением KeyError. Расписание — живые данные, которые правят люди руками, и пропущенное поле рано или поздно встретится. Первый надёжный способ защититься — метод словаря get, который принимает второй аргумент со значением по умолчанию: если ключа room нет, вместо падения программа получит строку вроде «уточняется» и продолжит работу дальше.

Второй способ — обернуть обращение к полю в блок try с перехватом KeyError, что уместно, когда отсутствие ключа означает более серьёзную проблему и её стоит явно залогировать вместо тихой заглушки. Для расписания практичнее первый способ: get с разумным значением по умолчанию не прерывает вывод всего расписания из-за одной неполной записи, он просто помечает пробел там, где он есть.

  • day.get('room', 'уточняется') не падает при отсутствии кабинета
  • day.get('teacher', 'не назначен') безопасно подставляет заглушку
  • прямое обращение day['room'] оправдано, только если поле обязано быть всегда
  • проверка 'room' in day до обращения — альтернатива get с той же защитой

Как записать изменения обратно в файл

Если программа умеет и читать расписание, и менять его — например, добавлять замену урока, — изменённую структуру Python нужно сохранить обратно в файл функцией json.dump. У неё стоит явно указать indent для читаемого форматирования с отступами и ensure_ascii равным False, иначе кириллические названия предметов превратятся в файле в нечитаемые экранированные юникод-коды вместо привычных букв.

Частые вопросы

Можно ли хранить расписание в CSV вместо JSON

Можно, если структура плоская и без вложенности, но расписание с несколькими полями на пару и разным числом пар в разные дни в CSV описывается неудобно, а вложенные структуры JSON справляются с этим естественно.

Что будет, если файл повреждён или пустой

json.load выбросит исключение json.JSONDecodeError, и его стоит перехватывать отдельно от KeyError, чтобы программа не падала целиком — вместо падения она сообщит о проблеме с самим файлом.

Нужно ли валидировать структуру после чтения

Для небольшого личного проекта достаточно get с заглушками, а для расписания на весь класс или школу полезно один раз проверить структуру целиком при загрузке, чтобы не находить пробелы по одному в процессе работы.

Как добавить новый день без переписывания всей структуры

Достаточно присвоить schedule нового ключа с названием дня и списком пар в значении, а затем сохранить весь словарь обратно через json.dump — остальные дни при этом не трогаются.