- 1.
- 2. Реализация
- 1. widget.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 файл и добавить дополнительные тексты в считанный файл.
Приложение будет выглядеть так.
Реализация
widget.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, и уже обращаясь у элементам массива, получвя из него объекты редактировать их