241-327_Deev_ASD/lab-3/quiz_json_adapter.cpp

109 lines
5.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* quiz_json_adapter.cpp — Реализация десериализации JSON → Quiz
*
* Весь процесс разбора сырых байт от сервера:
*
* reply->readAll() → QByteArray (бинарный буфер HTTP-ответа)
* ↓ QJsonDocument::fromJson()
* QJsonDocument (распарсенный JSON-документ)
* ↓ .array() или .object()
* QJsonArray / QJsonObject (узлы дерева JSON)
* ↓ toQuizList() / toQuiz() ← этот файл
* QList<Quiz> / Quiz (C++-объекты нашей модели)
*
* QJsonValue — универсальный тип, который может содержать
* число, строку, bool, массив, объект или null.
* Операция json["ключ"] всегда возвращает QJsonValue;
* затем вызывается один из методов-преобразователей:
* toInt(), toDouble(), toString(), toBool(), toObject(), toArray()
*/
#include "quiz_json_adapter.h"
#include <QJsonValue> // нужен для работы с элементами QJsonArray в цикле
// ─────────────────────────────────────────────────────────────────────────────
// toQuiz — десериализация одного объекта
// ─────────────────────────────────────────────────────────────────────────────
Quiz QuizJsonAdapter::toQuiz(const QJsonObject &json) const
{
/*
* Создаём пустой Quiz; все числа = 0, строки = "", bool = false.
* Поля заполняются по одному из соответствующих JSON-ключей.
*/
Quiz q;
/*
* json["id"] возвращает QJsonValue с типом Double (JSON не различает
* целое и вещественное). toInt() округляет до ближайшего целого.
*/
q.id = json["id"].toInt();
/*
* toString() возвращает QString. Если ключ отсутствует или тип не строка —
* вернётся пустая строка QString(), что безопасно.
*/
q.title = json["title"].toString();
q.description = json["description"].toString();
q.author = json["author"].toString();
/*
* Дата в JSON приходит строкой в формате ISO 8601:
* "2026-04-02T11:20:40.123456Z"
*
* Qt::ISODateWithMs — формат, совместимый с Django DateTimeField,
* он понимает как микросекунды, так и часовой пояс Z (UTC).
*
* Если строка пустая или формат не совпадает, QDateTime будет
* «недействительным» (isValid() == false) — без краша.
*/
q.createdAt = QDateTime::fromString(json["created_at"].toString(),
Qt::ISODateWithMs);
/*
* toInt(): JSON "time_limit": 40 → C++ int.
*/
q.timeLimit = json["time_limit"].toInt();
/*
* toBool(): JSON "is_published": true/false → C++ bool.
* Если ключ отсутствует, вернётся false (значение по умолчанию).
*/
q.isPublished = json["is_published"].toBool();
return q; // возврат по значению; компилятор применит NRVO (copy elision)
}
// ─────────────────────────────────────────────────────────────────────────────
// toQuizList — десериализация массива объектов
// ─────────────────────────────────────────────────────────────────────────────
QList<Quiz> QuizJsonAdapter::toQuizList(const QJsonArray &json) const
{
QList<Quiz> list;
/*
* reserve() выделяет память под json.size() элементов заранее,
* чтобы не было многократных реаллокаций при append().
*/
list.reserve(json.size());
/*
* Итерация по QJsonArray. Каждый элемент — QJsonValue,
* который может быть объектом, числом, строкой, null и т.д.
* Проверяем isObject() на случай, если сервер вернул
* смешанный массив или null-элементы.
*/
for (const QJsonValue &value : json) {
if (value.isObject()) {
/*
* toObject() приводит QJsonValue к QJsonObject,
* который затем передаётся в toQuiz() — переиспользуем
* логику одиночного парсинга.
*/
list.append(toQuiz(value.toObject()));
}
}
return list;
}