0.前言

JSON(JavaScript Object Notation)是一种轻量级的结构化数据格式,相对于XML语法更简洁。它具有6种基本数据类型:bool(true或false字符串表示)、double(对应JS中number)、string、array(值的列表)、object(键值对集合)、null 。

虽然cJSON和JsonCpp也是常用的C/C++ JSON解析器,但是在Qt框架中一般用Qt提供的解析类就行了。本文主要介绍QJson的使用,以及使用QTreeView展示和编辑JSON文档(代码链接在最后)。

目录

1.了解QJson

2.解析JSON

3.生成JSON

4.利用QTreeView展示和编辑JSON

5.参考


《偶然》 ----徐志摩

我是天空里的一片云,
偶尔投影在你的波心──
你不必讶异,
更无须欢喜──
在转瞬间消灭了踪影。

你我相逢在黑夜的海上,
你有你的,我有我的,方向;
你记得也好,
最好你忘掉
在这交会时互放的光亮!

1.了解QJson

Qt提供了多个类来分别表示JSON文档、节点、迭代器,这些类都是隐式共享的。

QJsonDocument:用于读写JSON文档。它包装完整的JSON文档,并且可以从基于UTF-8编码的文本表示形式以及Qt自己的二进制格式读取和写入此文档。可以使用QJsonDocument::fromJson() 将JSON文档从其基于文本的表示形式转换为QJsonDocument.toJson() 将其转换回文本。

QJsonParseError:用于表示JSON解析时发生的错误。

QJsonObject:表示键值对列表,其中键是唯一的字符串,而值由QJsonValue表示。QJson还提供了iterator和const_iterator来对QJsonObject进行迭代。要注意的是,一般的JSON结构,object键值对列表是无序的,array才有序,QJSON实现没有提供object有序的设置。

QJsonArray:表示值的列表,值由QJsonValue表示。

QJsonValue:存储数据的值,具有六种基本类型,可通过type() 方法获取其类型枚举:Bool、Double、String、Array、Object、Null,外加一个Undefined表示不确定的值。

在使用这些类时,先添加上对应的头文件。

2.解析JSON

一般常用的操作是读取文件用QByteArray初始化一个QJsonDocument,或者接收来自Http的object、array。下面的代码操作步骤为:读取文件,解析为QJsonDocument,遍历其中的QJsonObject和QJsonArray并获取值。操作起来相当的简单。

#include <QFile>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonValue>
#include <QDebug>//读取并解析JSON文档
bool LoadJson(const QString &filepath)
{//判断路径以及是否正常打开if(filepath.isEmpty())return false;QFile file(filepath);if(!file.open(QIODevice::ReadOnly|QIODevice::Text))return false;//读取数据后关闭文件const QByteArray raw_data=file.readAll();file.close();//解析为Json文档QJsonParseError json_error;QJsonDocument json_doc=QJsonDocument::fromJson(raw_data,&json_error);//是否正常解析Json数据if(json_doc.isNull()||json_doc.isEmpty()||json_error.error!=QJsonParseError::NoError)return false;//判断是object{}还是array[]的Jsonif(json_doc.isObject()){//解析文档中的Objectconst QJsonObject json_obj=json_doc.object();//[1]可以遍历objectQJsonObject::const_iterator iter;for (iter = json_obj.constBegin(); iter != json_obj.constEnd(); ++iter){qDebug()<<iter.key();const QJsonValue iter_val=iter.value();switch (iter_val.type()) {case QJsonValue::Object://如果是Object继续递归解析break;case QJsonValue::Array://如果是Array继续递归解析break;case QJsonValue::Bool:qDebug()<<iter_val.toBool();break;case QJsonValue::Double:qDebug()<<iter_val.toDouble();break;case QJsonValue::String:qDebug()<<iter_val.toString();break;case QJsonValue::Null: break;case QJsonValue::Undefined: break;default: break;}}//[2]也可以根据key查询object中的值if(json_obj.contains("key_name")){const QJsonValue json_val=json_obj.value("key_name");if(json_val.isString()){const QString str_val=json_val.toString();}else if(json_val.isArray()){//遍历数组}}}else if(json_doc.isArray()){//解析文档中的Arrayconst QJsonArray json_arr=json_doc.array();//遍历arrayQJsonArray::const_iterator iter;for (iter = json_arr.constBegin(); iter != json_arr.constEnd(); ++iter){qDebug()<<iter.i;const QJsonValue iter_val=*iter;if(iter_val.isString()){qDebug()<<iter_val.toString();}}for(int i=0;i<json_arr.count();i++){qDebug()<<i;const QJsonValue iter_val=json_arr.at(i);if(iter_val.isString()){qDebug()<<iter_val.toString();}}}return true;
}

3.生成JSON

生成和解析操作一样也很简单。

//生成JSON文档并导出
bool DumpJson(const QString &filepath)
{//判断路径if(filepath.isEmpty())return false;//这里构造一个Json,并添加模拟的数据QJsonDocument json_doc;QJsonArray json_arr;json_arr.insert(0,"Gong");json_arr.insert(1,"Jian");json_arr.insert(2,"Bo");json_arr.append("1992");QJsonObject json_obj;json_obj.insert("name","Qt");QJsonObject json_subobj{{"major",5},{"minor",12},{"patch",6}};//可以嵌套json_obj.insert("version",json_subobj);json_obj.insert("array",json_arr);//可以是object或者arrayjson_doc.setObject(json_obj);//转换为bytearray,Compact没有换行,Indented有换行可读性更强QByteArray json_data=json_doc.toJson(QJsonDocument::Indented);//判断是否正常打开QFile file(filepath);if(!file.open(QIODevice::WriteOnly))return false;file.write(json_data);file.close();return true;
}

QJsonDocument的toJson()接口有两个格式化参数,QJsonDocument::Compact更紧凑没有换行缩进等:

QJsonDocument::Indented 是更容易查看的带换行的格式:

4.利用QTreeView展示和编辑JSON

用QTreeView来展示JSON数据还是比较常见的,我写了一个简单的展示和编辑JSON数据的Demo(增删部分因为涉及到delegate,我就懒得写了,但是大致的框架是有的)。

其实思路很简单,解析并生成Tree就像生成二叉树:

void JsonTreeModel::parseObject(const QString &key, const QJsonObject &obj, JsonTreeItem *&item)
{//构造Object节点JsonTreeItem *child=new JsonTreeItem({{0,key},{1,"[Object]"}},JsonTreeItem::Object,item);item->appendChild(child);//遍历Object的keysconst QStringList keys=obj.keys();for(const QString &item_key:keys){//qDebug()<<"key:"<<item_key;parseValue(item_key,obj.value(item_key),child);}
}void JsonTreeModel::parseArray(const QString &key, const QJsonArray &arr, JsonTreeItem *&item)
{//构造Array节点JsonTreeItem *child=new JsonTreeItem({{0,key},{1,"[Array]"}},JsonTreeItem::Array,item);item->appendChild(child);//遍历Arrayfor(int i=0;i<arr.count();i++){parseValue("-",arr.at(i),child);}
}void JsonTreeModel::parseValue(const QString &key, const QJsonValue &val, JsonTreeItem *&item)
{QVariant the_val;//根据Value的类型进行下一步处理//如果是Object或Array就继续递归//如果是值就添加一个节点switch (val.type()) {case QJsonValue::Object:parseObject(key,val.toObject(),item);return;break;case QJsonValue::Array:parseArray(key,val.toArray(),item);return;break;case QJsonValue::Bool:the_val=val.toBool();break;case QJsonValue::Double:the_val=val.toDouble();break;case QJsonValue::String:the_val=val.toString();break;case QJsonValue::Null: break;case QJsonValue::Undefined: break;default: break;}//构造子节点JsonTreeItem *child=new JsonTreeItem({{0,key},{1,the_val}},JsonTreeItem::Value,item);item->appendChild(child);
}

导出编辑完后的Tree就像遍历二叉树:

QVariantMap JsonTreeModel::dumpObject(JsonTreeItem *&item) const
{QVariantMap json_obj; //QVariantMap对应QJsonObjectconst int child_count=item->childCount();for(int i=0;i<child_count;i++){JsonTreeItem *child=item->childItem(i);if(!child) continue;//为什么不用一个返回QVariant的函数之类的封装下?switch (child->type()) {case JsonTreeItem::Object:json_obj.insert(child->key(),dumpObject(child));break;case JsonTreeItem::Array:json_obj.insert(child->key(),dumpArray(child));break;case JsonTreeItem::Value:json_obj.insert(child->key(),dumpValue(child));break;default:break;}}return json_obj;
}QVariantList JsonTreeModel::dumpArray(JsonTreeItem *&item) const
{QVariantList json_arr; //QVariantList对应QJsonArrayconst int child_count=item->childCount();for(int i=0;i<child_count;i++){JsonTreeItem *child=item->childItem(i);if(!child) continue;switch (child->type()) {case JsonTreeItem::Object:json_arr.append(dumpObject(child));break;case JsonTreeItem::Array:json_arr.append(dumpArray(child));break;case JsonTreeItem::Value:json_arr.append(dumpValue(child));break;default:break;}}return json_arr;
}QVariant JsonTreeModel::dumpValue(JsonTreeItem *&item) const
{//QVariant对应QJsonValuereturn item->value();
}

对于TreeView的操作,我主要参考的官方示例:

每个节点由TreeItem类构成,相当于链表的一个节点,而每个节点有一个父节点和多个子节点。需要设计的就是对于每个节点,需要标记他的类型,是array、object还是value,这样便于和JSON文档转换。

待改进的地方:除了完善增删节点的功能,还需要使用delegate委托一个ComboBox来编辑节点类型是array、object还是value。

代码链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qt/QJsonAndTreeView

5.参考

Qt文档:https://doc.qt.io/qt-5/json.html

讨论:https://forum.qt.io/topic/49771/jsonmodel-for-qtreeview

别人的实现:https://github.com/anjinkristou/QJsonTreeWidget

别人关于Model的:https://github.com/benlau/qsyncable

QML felgo框架的:https://felgo.com/apps/avoid-cpp-models-qt

博客QJson:http://blog.sina.com.cn/s/blog_a6fb6cc90101gnxm.html

博客QJson:https://www.cnblogs.com/lifan3a/articles/7811434.html

Qt读写JSON,以及使用QTreeView展示和编辑JSON数据相关推荐

  1. .json格式是什么?如何快速打开.json文件?

    .json格式是什么? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于JavaScript语言的一个子集,但是它是独立于编程语言的,可以被多种编程语 ...

  2. 将对象mock填充数据 获取json格式对象,便于文档编辑

    将对象mock填充数据 获取json格式对象,便于文档编辑 <!--mock数据 java对象转json--><dependency><groupId>com.gi ...

  3. python json.load_python 读写json文件(dump, load),以及对json格式的数据处理(dumps, loads)...

    原博文 2018-04-22 09:11 − JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. 1.json.du ...

  4. QT中树控件QTreeView开发实例

    转自:http://mobile.51cto.com/symbian-268700.htm 本文讲解了QT中树控件QTreeView开发实例,对于QTreeView没有过多的讲解,那么不说废话了,看代 ...

  5. 【解决方案】QT读写文件

    下面的这些东西,在网上可能都会找到类似的文章,但是真正使用的时候,却没有办法打开对应的文件. 解决方案: 打开项目所在文件夹. 比如我这里的项目叫Test 可以看到前面两个有build-* 文件夹. ...

  6. android 之json对象解析并展示(含json解析源码)

    具体处理思路以及使用到的知识点: 1.使用android的异步处理 2.将要使用的功能(方法)进行封装,以便主类进行调用 3.前台展示要使用适配器模型(这里使用简单适配器(SimpleAdapter) ...

  7. 一文搞定Qt读写excel以及qt读写xml数据

    一文搞定Qt读写excel以及qt读写xml数据 最终的实现效果图 RC_ICONS = logo.ico .pro文件同级目录下加入 logo.ico 图标文件,运行文件,文件的图标就被写入软件 u ...

  8. qt中生成含有中文的json文件,读取含有中文的json文件

    引言 之前将变量保存并在本地生成json文件,由于其中含有中文,导致生成的json文件出现乱码,或者就是生成的json文件没有乱码,但是读取生成的json文件时出现乱码,不能正常解析json. 示例 ...

  9. QT读写文本文件编码设置

    QT读写文本文件编码设置 一.编码知识科普 Qt常见的两种编码是:UTF-8和GBK ★UTF-8:Unicode TransformationFormat-8bit,允许含BOM,但通常不含BOM. ...

最新文章

  1. 「实用」微信扫码 - 关注公众号后网站自动登录
  2. 怎么把数据存到MySQL_怎样将Arduino数据直接存储到MySQL
  3. 红河学院计算机科学与技术,2016年红河学院计算机科学与技术专业最低分是多少?...
  4. springcloud 创建子父项目_idea搭建springCloud----搭建父子项目(二)
  5. 重磅官宣:腾讯宣布再投500亿元助力共同富裕
  6. Web开发之二:什么是前端、什么是后端
  7. C语言数据结构各种排序算法(选择,直接,希尔,起泡等排序)
  8. tomcat安全加固配置手册
  9. 网上教学管理系统的设计与实现
  10. colab 挂载谷歌云盘
  11. java浪曦学习日志 异常类
  12. Hspice 反相器仿真
  13. 数据库课程设计——某商店进销存管理系统(附Java源码与课程设计报告)
  14. HDU1071微积分公式求曲线面积
  15. OpenGL实现在三维空间拖拽物体
  16. 02-AD软件基本使用第二讲(器件介绍)
  17. 【洛谷】P1567 统计天数
  18. LTE提高了频谱利用率吗?
  19. Avira AntiVir Personal 8 - FREE Antivirus/免费的杀毒软件
  20. LuaHelper高性能Lua插件

热门文章

  1. 简单的excel考勤表
  2. 数据工程指南高级技能:处理框架
  3. 45-网上商城数据库-商品分类数据操作(二)
  4. 鸿蒙大陆罪恶深渊哪里出,罪恶深渊 - 音阙诗听 - 5SING中国原创音乐基地
  5. 短视频评论的抓取及分析
  6. C语言递归函数——汉诺塔问题笔记
  7. 关于APPT2的问题记录AAPT2 error: check logs for details
  8. java基础:Linux系统下GiB和GB的换算
  9. 魔兽世界服务器卡顿原理,暴雪解释《魔兽世界》怀旧服卡顿原因 这款插件你还在用吗?...
  10. 一道智力题:有12个乒乓球,其中有一个不合规格,但不知是轻是重。要求用天平称三次,把这个坏球找出来。