QJson как библиотека для работы с JSON в Qt

  • Tutorial

Привет, хабр!

На хабре еще не писали про QJson — отличный и очень простой инструмент для работы с JSON на Qt. Вообще Qt рекоммендуют использовать XML — но мне кажется что в очень многих случаях он бывает чересчур уж избыточным или лишним. В некоторых случаях лучше использовать JSON. В этой заметке я расскажу как скачать, собрать и использовать QJson для работы с JSON в Qt.

Внимание! Этот пост — заметка. Все что вы тут прочитаете можно найти в гугле и на офф сайте проекта — но я думаю что такая заметка не будет лишней.


Получение


QJson — 3rd party, для того чтобы с ним работать, его нужно сначала получить и собрать. Это можно сделать двумя путями — с оффициального сайта проекта или с gitorious. Качаем, распаковываем и переходим к следующему этапу.

Установка


Разработчики QJson рекомендуют собирать через cmake.

Windows


set PATH=%PATH%;C:\path_to_cmake_\bin
cd path_where_i_unpacked_qjson
cd build
cmake -G "MinGW Makefiles" ..
mingw32-make
mingw32-make install


Linux/Mac


cd where_i_downloaded_qjson
mkdir build
cd build
cmake ..
make
sudo make install


Начинаем работу


QJson позволяет работать с JSON на основе QVariant (QVariantMap, QVariantList) что дает ему гибкость. Он умеет парсить, писать JSON и сиреализировать QObject'ы.

Для начала — добавим в .pro файл строчку:
LIBS    += -lqjson


Теперь наш проект зависит от qjson и умеет работать с ним.

Парсим QJson


#include<qjson/parser.h>

QVariant parseJSON(const QString &json)
{
   QJson::Parser parser; // парсер для json'а
   bool ok; // false если будут ошибки
   return parser.parse (json, &ok); // QVariant
}


Пусть мы будем парсить этот JSON:
{
   "encoding" : "UTF-8",
   "plug-ins" : [
       "python",
       "c++",
       "ruby"
      ],
   "indent" : { "length" : 3, "use_space" : true }
}


Вот этим кодом:
QJson::Parser parser;
bool ok;

QVariantMap result = parser.parse (json, &ok).toMap();
if (!ok) {
  qFatal("Пока парсили возникла ошибочка - беда-то.");
  exit (1);
}

qDebug() << "encoding:" << result["encoding"].toString();
qDebug() << "plugins:";

foreach (QVariant plugin, result["plug-ins"].toList()) {
  qDebug() << "\t-" << plugin.toString();
}

QVariantMap nestedMap = result["indent"].toMap();
qDebug() << "length:" << nestedMap["length"].toInt();
qDebug() << "use_space:" << nestedMap["use_space"].toBool();


Вывод в debug-консоль будет такой:
encoding: "UTF-8"
plugins:
  - "python"
  - "c++"
  - "ruby"
length: 3
use_space: true


Пишем из QVariant в JSON


Я только оставлю сдесь этот пример:
QVariantList people;

QVariantMap bob;
bob.insert("Name", "Bob");
bob.insert("Phonenumber", 123);

QVariantMap alice;
alice.insert("Name", "Alice");
alice.insert("Phonenumber", 321);

people << bob << alice;

QJson::Serializer serializer;
QByteArray json = serializer.serialize(people);

qDebug() << json;


Вывод в debug-консоли будет таким:
"[ { "Name" : "Bob", "Phonenumber" : 123 },
   { "Name" : "Alice", "Phonenumber" : 321 } ]"


Замечательно, не так-ли?

Сериализация QObject


Также возможнa сериализация экземпляра QObject в JSON. Все атрибуты класса определяется как свойства и будут упорядочены. Предположим, что определение класса выглядит следующим образом:
class Person : public QObject
{
  Q_OBJECT

  Q_PROPERTY(QString name READ name WRITE setName)
  Q_PROPERTY(int phoneNumber READ phoneNumber WRITE setPhoneNumber)
  Q_PROPERTY(Gender gender READ gender WRITE setGender)
  Q_PROPERTY(QDate dob READ dob WRITE setDob)
  Q_ENUMS(Gender)

public:
     Person(QObject* parent = 0);
     ~Person();

    QString name() const;
    void setName(const QString& name);

    int phoneNumber() const;
    void setPhoneNumber(const int  phoneNumber);

    enum Gender {Male, Female};
    void setGender(Gender gender);
    Gender gender() const;

    QDate dob() const;
    void setDob(const QDate& dob);

  private:
    QString m_name;
    int m_phoneNumber;
    Gender m_gender;
    QDate m_dob;
};


Вот этот код превратит объект Person в JSON:
Person person;
person.setName("Flavio");
person.setPhoneNumber(123456);
person.setGender(Person::Male);
person.setDob(QDate(1982, 7, 12));

QVariantMap variant = QObjectHelper::qobject2qvariant(&person);
Serializer serializer;
qDebug() << serializer.serialize( variant);


В консоли будет следующий вывод:
{ "dob" : "1982-07-12",
  "gender" : 0,
  "name" : "Flavio",
  "phoneNumber" : 123456 }


Также возможно парсить JSON в QObject. Представим, что вышеуказанный JSON есть в каком-то QString.
Parser parser;
QVariant variant = parser.parse(json); // json - наш JSON в QString

Person person;
QObjectHelper::qvariant2qobject(variant.toMap(), &person); // запишет в person пропертис из json


Полное API


Отлично описано на английском языке тут.

Мой комментарий


Кому это может быть полезно? Да кому угодно! Любому разработчику которому надо хранить информацию в легком или user-friendly формате.

Спасибо за внимание.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 32
  • +3
    Хорошая и полезная статья.
    Очень актуально, тем более JSON набирает популярность.
    • 0
      Недавно выбирал чем парсить JSON под проект с Qt, тоже выбрал QJson.
      • 0
        А разве есть разумные альтернативы? (ну кроме как написать свой парсер)
        • 0
          Есть. Например, qt-json: github.com/ereilin/qt-json
          Делает то же самое — преобразует JSON в QVariantMap и обратно, но при этом код намного чище (всего два файла: .h и .cpp), и никакой дополнительной сборки не требуется (можно просто включить файлы в свой проект, лицензия BSD).
          Активно юзаем в нескольких проектах — нареканий никаких.
          • 0
            А умеет QObject в Json и обратно?
            • 0
              Напрямую нет, но решение тривиально — зарегистрировать свой класс в QMetaType, после чего он будет без проблем конвертиться в QVariant и обратно, который, в свою очередь, можно конвертить в JSON.
              • 0
                Там другое имелось в виду, но сериализация десериализация пишется на раз два три.
            • 0
              Выбрал бы его с удовольствием но там где он мне нужен его лицензия GPL не подойдет. А вот у QJson LGPL что уже намного лучше.
            • 0
              boost::property_tree :-)
          • 0
            Спасибо за обзор, хорошая либа. Я её юзал когда надо было общаться с сервером через API, выдающий json, и допиливать который для выдачи xml никто не собирался. Выручила =)
            • 0
              Спасибо за заметку.
              • +1
                Юзаем маленький k8json, который в принципе пошустрее и умеет скипать записи вместо полного парсинга, что сильно скорость поиска увеличивает по массивам. А вообще в Qt5 есть встроенная поддержка json'а, видел, что народ просто этот модуль целиком выдирал и юзал с Qt4!
                • 0
                  А вообще в Qt5 есть встроенная поддержка json'а, видел, что народ просто этот модуль целиком выдирал и юзал с Qt4!


                  Вы про qjsondb?
                    • +1
                      Спасибо. Теперь буду знать как называется. Сейчас опробую на новеньком Qt5.
                      • 0
                        Вот и я думаю, что лучше это юзать по возможности, а не юзать лисапеды, которые скоро вымрут как класс.
                        • 0
                          Ну, полный переезд на Qt5 состоится не совсем скоро, ещё живы даже Qt3-проекты. И не все старые системы Qt5 будет поддерживать, к сожалению. Так что лисапеды живы и будут жить, как ни крути =)
                          • 0
                            Я в дикой природе живых Qt3 проектов не видел, всякие МСВС не в счет, это нишевые. Старый embedded, где Qt5 не взлетит тоже в общем-то уже прошлое.
                            Да и лучше тогда этот QJsonDocument на Qt4 накатить, чтобы потом проще было на Qt5 переезжать
                            • 0
                              Ну, насчёт последнего пункта согласен =)
                              А вот активные троечные проекты видел, и даже собирал. Правда, поробуй теперь вспомнить их названия, года два назад это было.
                              • 0
                                Меня больше волнует Qt3Support, которого немало еще осталось.
                              • 0
                                А что, нишевые проекты — не проекты? У нас есть в дикой природе нишевой проект на Qt3, но уже в состоянии долгоиграющей поддержки. Новая версия на Qt4 уже сделана, но там случилась такая революция по всем фронтам, что отмашку на развёртывание дадут ещё очень не скоро.

                                Кстати, а есть порт QJsonDocument для Qt4 в качестве отдельной библиотеки? Или оно просто без бубна взлетает?
                  • +2
                    Может быть «сериализация»?
                    • 0
                      «Сиреализация QObject» это да, самая цепляющая часть статьи.
                      • +2
                        Реализация на Си → Сиреализация :)
                    • +3
                      Кстати если нужно только парсить (не строить) несложный JSON, то проще использовать QtScript для разбора — не надо ковыряться с поддержкой сторонней библиотеки.
                      • 0
                        На самом деле, QJson простая как болт и очень быстро прикручивается (и есть в репозиториях большинства Linux-дистрибутивов). Можно, конечно, и через QtScript, но более громоздко и топорно :)

                        Строить JSON тоже можно — классический JSON2.js под QtScript прекрасно работает и уже несколько лет живёт у нас в одном из проектов.
                        • 0
                          Да я не спорю, просто иногда бывает такой проект, в котором подключение любой(!) сторонней библиотеки это недели бюрократических согласований. И при этом задачи возложенные на JSON парсер настолько минимальны что возится с библиотекой и самое главное бюрократией не имеет смысла.
                          • 0
                            Это где такой маразм? Да и что мешает просто пару файлов в проект воткнуть если они под BSD?
                            • 0
                              Поверь, всякий маразм бывает. Некоторым даже запрещают использовать весь opensource кроме «сертифицированного в ФСБ».
                      • НЛО прилетело и опубликовало эту надпись здесь
                        • 0
                          Заметка хорошая, но зачем столько орфографических ошибок?
                          • 0
                            Добавлю свои пять копеек.

                            У меня под Win 7 с Qt 4.8.1 только The GUI way сборки заработал. Пришлось для сборки установить GNU Cmake.

                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.