109 lines
5.4 KiB
C++
109 lines
5.4 KiB
C++
/*
|
||
* 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;
|
||
}
|