Qt解析Json数据

前言

本文主要介绍了使用Qt框架编程时如何解析JSON数据的一种方法。JSON是英文JavaScript Object Notation 的缩写,它是一种轻量级的数据交换格式,具有方便阅读和编写的优点,同时也易于机器解析和生成。JSON数据格式应用广泛,能够用于多种语言之间的数据交换。当前开源的C++JSON解析库有大概几十种,比较著名的有jsoncpp、nlohmann/json、rapidjson、jsonxx等。除此之外Qt5.0以上的版本也提供了JSON数据的读写支持。本文以jsoncpp库为例介绍如何使用第三方库实现JSON数据的读写。

1.下载 jsoncpp 源码

点击下载地址打开如下如所示页面,下载jsoncpp源码。
在这里插入图片描述

2.编译

按照国际惯例,这里使用Cmake来编译jsoncpp动态库。笔者是在Win10系统下编译的,首先打开cmake-gui,然后选择下载的jsoncpp源码路径,并设置好编译目录。如下图所示
在这里插入图片描述
依次点击 Configure、Generate、Open Project 按钮,打开生成的VS工程。
在这里插入图片描述
在解决方案上右键弹出菜单,选择【批生成】菜单项,在弹出的页面中勾选 “ALL_BUILD Debug"和"ALL_BUILD Release” ,如图所示
在这里插入图片描述
点击生成按钮,等待编译完成,查看是否生成对应的动态库文件。这种批生成其实也生成了对应debug和release版本的静态库。生成结束后打开build目录中的lib文件夹,可以看到Debug和Release两个目录。打开其中一个可以看到如下图所示内容
在这里插入图片描述

3.JSON数据读写示例

新建一个带界面的QT应用程序,把编译好的动态库引入到工程中。在pro文件中添加如下代码

INCLUDEPATH += $$PWD/include

CONFIG(debug) {
    message(debug mode)
    LIBS += -L$$PWD/lib -ljsoncppd
} else {
    message(release mode)
    LIBS += -L$$PWD/lib -ljsoncpp
}

DESTDIR = $$PWD/bin

其中include 目录中包含jsoncpp的头文件,lib目录下是jsoncpp动态库lib文件。并将对应的dll 文件拷贝到bin目录下。目录结构如下图所示
在这里插入图片描述

简单的创建一个界面来完成json数据的读写操作,UI如下图所示,左侧是一个用户信息表,右边是添加用户信息的页面。在输入框中输入用户信息,点击保存按钮新增用户信息,并把用户信息以JSON格式保存到文件中。点击刷新按钮,把文件中所有的用户信息读取到表格中。
在这里插入图片描述
保存按钮的槽函数为slot_saveUserInfo()。 writeDataToFile()函数将用户信息转为json数据格式,并写入到bin目录下的userList.json文件中。

void MainWindow::slot_saveUserInfo()
{
    UserInfo userInfo;
    userInfo.name = ui->le_name->text().trimmed();
    userInfo.phone = ui->le_no->text().trimmed();
    userInfo.address = ui->le_address->text().trimmed();

    m_userList.append(userInfo);

    writeDataToFile();
}


void MainWindow::writeDataToFile()
{
    QString jsonFileName = qApp->applicationDirPath() + "/userList.json";

    Json::Value userListVal;
    for (int i = 0; i < m_userList.size(); i++)
    {
        Json::Value userInfo;
        userInfo["name"] = m_userList[i].name.toLocal8Bit().data();
        userInfo["phone"] = m_userList[i].phone.toLocal8Bit().data();
        userInfo["address"] = m_userList[i].address.toLocal8Bit().data();

        userListVal.append(userInfo);
    }

    Json::Value jsonRoot;
    jsonRoot["userList"] = userListVal;

    Json::StyledWriter writer;
    std::string jsonData = writer.write(jsonRoot);

    printf("jsonData:\n %s ", jsonData.c_str());

    QFile jsonFile(jsonFileName);
    if (jsonFile.open(QIODevice::WriteOnly))
    {
        qint64 nRet = jsonFile.write(jsonData.c_str());
        if (nRet < 0)
        {
            qDebug() << "write data failed!";
        }
        jsonFile.close();
    }
}

在页面上添加几条数据,查看userList.json文件内容,由于编码问题,中文是以Unicode编码的形式保存的。

{
   "userList" : [
      {
         "address" : "\u5317\u4eac\u5e02\u6d77\u6dc0\u533a\u5f20\u5bb6\u6c9f\u6751",
         "name" : "\u5f20\u4e09",
         "phone" : "18078665544"
      },
      {
         "address" : "\u5317\u4eac\u5e02\u6d77\u6dc0\u533a\u674e\u5bb6\u6c9f\u6751",
         "name" : "\u674e\u56db",
         "phone" : "18078665599"
      }
   ]
}

点击刷新按钮,将文件中的数据,读取到页面的列表中。刷新按钮的响应函数是slot_refreshUserTable(),代码如下

void MainWindow::slot_refreshUserTable()
{
    QString jsonFileName = qApp->applicationDirPath() + "/userList.json";

    QFile jsonDataFile(jsonFileName);
    if (jsonDataFile.open(QIODevice::ReadOnly))
    {
        std::string jsonStr = jsonDataFile.readAll().data();
        Json::Value jsonRoot;
        Json::Reader reader;
        if (reader.parse(jsonStr, jsonRoot))
        {

            Json::Value userListVal = jsonRoot["userList"];
            if (userListVal.isArray())
            {
                Json::Value::iterator iter = userListVal.begin();
                m_userList.clear();
                while (iter != userListVal.end())
                {
                    Json::Value userInfo = userListVal[iter.index()];

                    UserInfo stUserInfo;
                    stUserInfo.name = userInfo.get("name", "").asCString();
                    stUserInfo.phone = userInfo.get("phone", "").asCString();
                    stUserInfo.address = userInfo.get("address", "").asCString();
                    m_userList.append(stUserInfo);

                    iter++;
                }

                updateTableWidget();
            }
        }
    }
}

页面显示效果
在这里插入图片描述

4.jsoncpp核心类详解

从上面的示例中,可以看到jsoncpp使用起来非常便捷,其核心类为Json::Value 、Json::StyledWriter、Json::Reader。其中Json为命名空间。

  • Value
    该类是泛型数据表示类,json格式支持的各种数据类型都可以用这个类来存储,并能在使用时转换成实际的数据类型。下面的枚举ValueType 描述了Value类支持的所有数据类型。
		enum ValueType {
		  nullValue = 0, ///< 'null' value
		  intValue,      ///< signed integer value
		  uintValue,     ///< unsigned integer value
		  realValue,     ///< double value
		  stringValue,   ///< UTF-8 string value
		  booleanValue,  ///< bool value
		  arrayValue,    ///< array value (ordered list)
		  objectValue    ///< object value (collection of name/value pairs).
		};

Value的赋值

	Json::Value userListVal; //arrayValue 类型
    for (int i = 0; i < m_userList.size(); i++)
    {
        Json::Value userInfo; //objectValue 类型,直接通过下标赋值
        userInfo["name"] = m_userList[i].name.toLocal8Bit().data();
        userInfo["phone"] = m_userList[i].phone.toLocal8Bit().data();
        userInfo["address"] = m_userList[i].address.toLocal8Bit().data();

        userListVal.append(userInfo); //arrayValue 类型添加数据
    }

Value类型判断,通过调用Value提供的一组API可以轻松的辨别数据的具体类型。

  bool isNull() const;
  bool isBool() const;
  bool isInt() const;
  bool isInt64() const;
  bool isUInt() const;
  bool isUInt64() const;
  bool isIntegral() const;
  bool isDouble() const;
  bool isNumeric() const;
  bool isString() const;
  bool isArray() const;
  bool isObject() const;

Value类型转换, 通过下面的API可以将Value转换成实际数据类型的数据。

  String asString() const; 
  Int asInt() const;
  UInt asUInt() const;
#if defined(JSON_HAS_INT64)
  Int64 asInt64() const;
  UInt64 asUInt64() const;
#endif // if defined(JSON_HAS_INT64)
  LargestInt asLargestInt() const;
  LargestUInt asLargestUInt() const;
  float asFloat() const;
  double asDouble() const;
  bool asBool() const;
  • StyledWriter
    StyledWriter 类能够把Json::Value组织起来的数据,转换成JSON格式的字符串。这个类有两个兄弟类 Writer。StyledWriter与Writer的区别是StyledWriter类输出的JSON字符串含有换行符,易于阅读,而Writer输出的JSON字符串就是一行数据,中间没有换行符。StyledWriter和Writer类的使用也很简单,直接调用write函数就好了!
	Json::StyledWriter writer;
    std::string jsonData = writer.write(jsonRoot);
  • Reader
    Reader类的功能是把JSON格式的字符串数据转换成Json::Value存储的数据。程序中再根据Json::Value的具体类型使用这些数据。Reader类的用法也非常简单。
 		std::string jsonStr = jsonDataFile.readAll().data();
        Json::Value jsonRoot;
        Json::Reader reader;
        if (reader.parse(jsonStr, jsonRoot))
        {
        	//正确解析,DoSomthing
		}

以上就是本文的所有内容,如有疑问欢迎您留言讨论。本文demo下载地址

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凝望星辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值