- 1.
- 2. Реалізація
- 1. віджет.h
- 2. widget.cpp
- 3. Висновок
Розглянемо невеликий приклад формування JSON документа з, наприклад, тексту і заголовка цього тексту.
Наприклад текст має:
- Заголовок - First Title
- Контент - First Content
І т.д.
Додаватимемо цей текст у QJsonObject , який будемо додавати в масив текстів QJsonArray . Масив об'єктів перебуватиме у загальному робочому QJsonObject , який зберігатимемо у файл.
Все це робитимемо через графічний інтерфейс, в якому є:
- QLineEdit - titleLineEdit - містить заголовок тексту, який потрібно додати
- QTextEdit - contentTextEdit - містить вміст тексту, який потрібно додати
- QTextEdit - jsonDocumentTextEdit - перегляд JSON документа
- QPushButton - addButton - кнопка для додавання нового тексту в JSON
- QPushButton - clearButton - кнопка для видалення всіх текстів з поточного QJsonObject
- QPushButton - saveButton - кнопка для збереження JSON документа у файл
- QPushButton - loadButton - кнопка для зчитування JSON з файлу
В даному випадку зможемо рахувати JSON файл та додати додаткові тексти до ліченого файлу.
Програма виглядатиме так.
Реалізація
віджет.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QJsonObject> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = nullptr); ~Widget(); private: // Слот добавления нового текста в массив текстов void onAddButtonClicked(); // Слот удаления всей информации о текстах в текущем объекте void onClearButtonClicked(); // Слот сохранения текстов в json файл void onSaveButtonClicked(); // Слот загрузки текстов в программу из json файла void onLoadButtonClicked(); Ui::Widget *ui; // Текущий json объект, с которым производится работа QJsonObject m_currentJsonObject; }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QFileDialog> #include <QFile> #include <QDir> #include <QJsonObject> #include <QJsonArray> #include <QJsonDocument> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // Подключение слотов обработчиков к сигналам клика по кнопкам connect(ui->addButton, &QPushButton::clicked, this, &Widget::onAddButtonClicked); connect(ui->clearButton, &QPushButton::clicked, this, &Widget::onClearButtonClicked); connect(ui->saveButton, &QPushButton::clicked, this, &Widget::onSaveButtonClicked); connect(ui->loadButton, &QPushButton::clicked, this, &Widget::onLoadButtonClicked); } Widget::~Widget() { delete ui; } void Widget::onAddButtonClicked() { // Создаём объект текста QJsonObject textObject; textObject["title"] = ui->titleLineEdit->text(); // Устанавливаем заголовок текста textObject["content"] = ui->contentTextEdit->toPlainText(); // Устанавливаем содержание текста QJsonArray textsArray = m_currentJsonObject["texts"].toArray(); // Забираем текущий массив текстов, даже если он не существует, он будет создан автоматически textsArray.append(textObject); // Добавляем объект текста в массив m_currentJsonObject["texts"] = textsArray; // Сохраняем массив обратно в текущий объект // Устанавливаем текст всего Json объекта в текстовое поле для проверки ui->jsonDocumentTextEdit->setText(QJsonDocument(m_currentJsonObject).toJson(QJsonDocument::Indented)); } void Widget::onClearButtonClicked() { m_currentJsonObject = QJsonObject(); // Пересоздаём новый текущий QJsonObject ui->jsonDocumentTextEdit->clear(); // Очищаем текстовое поле // Устанавливаем текст всего Json объекта в текстовое поле, чтобы увидеть, что это пустой объект. // Увидите следующее -> {} ui->jsonDocumentTextEdit->setText(QJsonDocument(m_currentJsonObject).toJson(QJsonDocument::Indented)); } void Widget::onSaveButtonClicked() { // С помощью диалогового окна получаем имя файла с абсолютным путём QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save Json File"), QString(), tr("JSON (*.json)")); QFileInfo fileInfo(saveFileName); // С помощью QFileInfo QDir::setCurrent(fileInfo.path()); // установим текущую рабочую директорию, где будет файл, иначе может не заработать // Создаём объект файла и открываем его на запись QFile jsonFile(saveFileName); if (!jsonFile.open(QIODevice::WriteOnly)) { return; } // Записываем текущий объект Json в файл jsonFile.write(QJsonDocument(m_currentJsonObject).toJson(QJsonDocument::Indented)); jsonFile.close(); // Закрываем файл } void Widget::onLoadButtonClicked() { // Выбираем файл QString openFileName = QFileDialog::getOpenFileName(this, tr("Open Json File"), QString(), tr("JSON (*.json)")); QFileInfo fileInfo(openFileName); // С помощью QFileInfo QDir::setCurrent(fileInfo.path()); // установим текущую рабочую директорию, где будет файл // Создаём объект файла и открываем его на чтение QFile jsonFile(openFileName); if (!jsonFile.open(QIODevice::ReadOnly)) { return; } // Считываем весь файл QByteArray saveData = jsonFile.readAll(); // Создаём QJsonDocument QJsonDocument jsonDocument(QJsonDocument::fromJson(saveData)); // Из которого выделяем объект в текущий рабочий QJsonObject m_currentJsonObject = jsonDocument.object(); // Очищаем текстовое поле ui->jsonDocumentTextEdit->clear(); // И устанавливаем в проверочное текстовое поле содержимое Json объекта ui->jsonDocumentTextEdit->setText(QJsonDocument(m_currentJsonObject).toJson(QJsonDocument::Indented)); }
Висновок
У даному конкретному випадку використовується QFileDialog, щоб отримати шлях до файлу, що записується, і відкривається файлу. Звичайно, з маніпуляцій з вже існуючим файлом доступне лише додавання нових текстів і можна відкрити будь-який коректний JSON документ, а потім додати до нього текст. Але для прикладу вважаю, що більше не потрібно.
Скажите пожалуйста, в 55 строке получаем saveFileNam, это видимо полное имя файла. Но где потом сообщается полный путь файлу json при его записи?
В saveFileName будет полный путь к файлу с его именем. В диалоге просто вводите имя файла с расширением, а QFileDialog возвращает имя файла и полный путь к нему.
Можете увидеть это, если добавите вывод в qDebug
А через fileInfo я выдернул путь к файлу, чтобы установить рабочую директорию через QDir::setCurrent();, чтобы указать, где именно сохраняется файл. А когда я передаю saveFileName в QFile, даже с наличием пути в имени, всё будет нормально работать, путь должен быть отброшен автоматически.
Спасибо.
Скажите пожалуйста, зачем 65 строка? написал по образцу часть кода, выдало ошибку D:\QTProject\ReaderResume\main.cpp:58: ошибка: return-statement with no value, in function returning 'int' [-fpermissive]
return;
^
Без return работает
зачем вы слот написали с возвращаемым значением int?
У вас сигнатура в вашем коде так написана
слоту обычно не требуется возвращаемое значение.
return прерывает выполнение метода, чтобы не шло дальше, если файл не открылся в данном случае.
Спасибо
Скажите пожалуйста, как добавить в массив QJsonArray другой массив QVector<QString> TextArra?
Как я понял, это можно сделать в цикле поочередно для каждого члена массива, но можно ли сразу перевести одной командой?
Думаю, что через алгоритмические методы вставки из стандартной библиотеки и использование итераторов с лямбда функциями можно написать и в одну строку.
Но судя по вашим вопросам, могу сказать, что вы не знакомы со всем этим зоопарком, поэтому пока не забивайте себе этим голову, в процессе работы сами прийдёте к использованию данного функционала. Так что сделайте через цикл поочерёдно. Просто напишите
Также вы можете сами написать эту вспомогательную команду.
Спасибо. И скажите пожалуйста, как перевести QString в QJsonValue
QJsonValue::fromVariant(const QVariant& variant);
Спасибо.
Скажите пожалуйста, в json файле размещен массив, в этот массив нужно добавить еще один элемент массива. Но считывать весь массив - тратить дополнительное время. Можно ли, при условии, что я знаю, что там только один массив, как то быстро добавить один элемент?
Возможно, через итератор можно будет сделать. Я не проверял. сам по себе метод toArray() возвращает копию массива...
На первый взгляд я не увидел необходимой возможности, хотя подумал об этом.
Возможно с итераторами через метод find, можно будет взять массив и уже в нём покопаться. Но не факт.
А можно сразу перейти в конец документа, если нет ], то записывать с начала, а если есть ] , то ставить запятую и дописывать еще один элемент?
Это уже вручную нужно реализовывать. Только это не нужно, пока действительно не будет проблемы по производительности.
А вообще, если нужно хранение данных, то возможно и насчёт базы данных стоит подумать. Хотя бы SQLite можно использовать. Это будет эффективнее.
Как отредактировать данные?
Смотря что хотите и в каком виде эти данные. Если в текстовом, то их нужно прочитать, перевести в QJsonDocument, из него достать массив connect, и уже обращаясь у элементам массива, получвя из него объекты редактировать их