目录
json格式简介
json可以理解为一种多级键值对的结构,例如:
{
"name" : "Xiao Ming",
"age" : 10
}
上面这个简单结构表示一个学生信息,包含2个键值对。
我们来看一个复杂点的:
{
"students" : [
{
"name" : "Xiao Ming",
"age" : 10
},
{
"name" : "Xiao Hong",
"age" :8
}
],
"classes" : ["one", "two", "three"],
"teacher" : {
"name" : "FangFang",
"age" : 23
}
}
上面这个多级结构表示多个学生和多个班级
- 键students对应的值是一个数组,数组里面放了2个json对象;
- 键classes对应的值是一个数组,数组里面放了3个字符串;
- 键teacher对应的值是一个json对象,里面放的是老师信息。
可以做一个简单的总结:
- 大括号{}表示一个json对象
- 中括号[]表示一个json数组,数组内容可以是普通的值类型,也可以是一个json对象
- 冒号左边是键,右边是值,值可以基础类型、数组和json对象。
QJson模块介绍
Qt的Json模块主要涉及3个数据结构类(QJsonObject、QJsonValue、QJsonArray)和1个序列化和反序列化类(QJsonDocument)。下面我们介绍下这4个基础类。
QJsonValue、QJsonObject、QJsonArray
- QJsonValue表示一个Json值,对应例子中冒号:右边的部分
- QJsonObject表示一个Json对象,就是例子中大括号{}的部分。
- QJsonArray表示一个Json值数组,对应例子中中括号[]的部分
- QJsonDocument是负责序列化和反序列化,比如将Json对象转换为QByteArray,将QByteArray转化为Json对象等。
QJson模块基本用法
QJsonValue
支持的类型
QJsonValue表示Json值,前面说过,值可以是基本类型、QJsonArray和QJsonObject,具体如下:
QJsonValue::Type | 描述 |
---|---|
QJsonValue::Null | null值 |
QJsonValue::Bool | 存储的是bool值,可以通过toBool转换为bool类型 |
QJsonValue::Double | 存储的是double值,可以通过toDouble转换为double类型 |
QJsonValue::String | 存储的是字符串类型,可以通过toString转换为QString类型 |
QJsonValue::Array | 存储的是数组,可以通过toArray转换为QJsonArray类型 |
QJsonValue::Object | 存储的json对象,可以通过toObject转换为QJsonObject类型 |
可以通过type方法获取当前存储的类型,例如:
QJsonValue value(false);
qDebug() << value.type();
当然还有一些类型判断,如下:
QJsonValue value(false);
qDebug() << value.isBool();
qDebug() << value.isObject();
...
构建
可以通过支持的类型直接构建,例如:
QJsonValue value(false);
QJsonValue value(1);
QJsonValue value("XiaoMing");
QJsonValue value(QJsonArray({ 1, 2 }));
QJsonValue value(QJsonObject({ { "name", "XiaoMing" }, { "age", 10 } }));
QJsonObject
构建
1 . 可以通过初始化列表构造QJsonObject对象,例如:
QJsonObject object({ { "name", "XiaoMing" }, { "age", 15 } });
qDebug().noquote() << QJsonDocument(object).toJson();
输出:
{
"age": 15,
"name": "XiaoMing"
}
2 . 另外大家发现没,上面初始化列表正好是个QVarientMap或者QVarientHash,QVarientMap和QVarientHash里放的就是多个键值对,也正好符合Json对象的形式,所以,QJsonObject提供了下面两个静态方法:
static QJsonObject fromVariantMap(const QVariantMap &map);
static QJsonObject fromVariantHash(const QVariantHash &map);
当然也可以将QJsonObject转换为QVarientMap或者QVarientHash
QVariantHash toVariantHash() const;
QVariantMap toVariantMap() const;
3 . 动态构建QJsonObject,通过使用insert方法添加键值对,例如:
object.insert("name", "XiaoMing");
object.insert("age", 15);
qDebug().noquote() << QJsonDocument(object).toJson();
输出:
{
"age": 15,
"name": "XiaoMing"
}
注意
- QJsonObject中插入键值对后是会按键排序的,不会保持insert的顺序,类似QMap。
- QJsonObject中存储容量是有上限的,源码中,插入新值会执行reserveSpace,里面有个容量上限
int Base::reserveSpace(uint dataSize, int posInTable, uint numItems, bool replace)
{
Q_ASSERT(posInTable >= 0 && posInTable <= (int)length);
if (size + dataSize >= Value::MaxSize) {
qWarning("QJson: Document too large to store in data structure %d %d %d", (uint)size, dataSize, Value::MaxSize);
return 0;
}
...
}
enum {
MaxSize = (1<<27) - 1
};
取值、 查找、遍历、删除
QJsonObject提供了容器类的基本都有的常规方法,如下:
QJsonObject object({ { "name", "XiaoMing" }, { "age", 15 } });
// 取值
qDebug() << object.value("name");
qDebug() << object["name"];
// 查找
qDebug() << object.contains("name");
auto iter = object.find("name");
// 遍历
for (auto iter = object.begin(); iter != object.end(); iter++)
qDebug() << iter.key() << iter.value();
// 删除
object.remove("name");
QJsonArray
QJsonArray可以理解为Array of QJsonValue,里面放置的是一组QJsonValue,而不是QJsonObject。
构建
1.初始化列表构建
QJsonArray array({1});
QJsonArray array({"XiaoMing", "XiaoHong"});
2.动态构建
QJsonArray array;
array.append(1);
array.append(QJsonObject({ { "name", "XiaoMing" }, { "age", 10 } }));
array.insert(0, "XiaoMing");
qDebug().noquote() << QJsonDocument(array).toJson();
输出:
[
"XiaoMing",
1,
{
"age": 10,
"name": "XiaoMing"
}
]
3.从QStringList和QVarient转换
static QJsonArray fromStringList(const QStringList &list);
static QJsonArray fromVariantList(const QVariantList &list);
取值、删除、修改、遍历
// 取值
QJsonArray array({"XiaoMing", "XiaoHong"});
qDebug() << array[0];
// 删除
array.remove(0);
// 替换
array.replace(0, "DaWang");
// 遍历
for (auto value : array)
qDebug() << value;
QJsonDocument之序列化和反序列化
QJsonDocument可以理解为一个QJson序列化和反序列化的工具类。
序列化
QJsonDocument支持从QJsonObject和QJsonArray构造:
QJsonDocument(const QJsonObject &object)
QJsonDocument(const QJsonArray &array)
或者通过set方法设置数据:
void setArray(const QJsonArray &array)
void setObject(const QJsonObject &object)
然后,使用toJson方法序列化成QByteArray,例如:
QJsonObject object({ { "name", "XiaoMing" }, { "age", 15 } });
qDebug().noquote() << QJsonDocument(object).toJson();
输出:
{
"age": 15,
"name": "XiaoMing"
}
另外,toJson可以传QJsonDocument::Compact参数来获取压缩后的序列化结果,压缩的结果如下:
{"age":12,"name":"XiaoMing"}
反序列化
QJsonDocument提供了静态方法fromJson来创建QJsonDocument对象:
// error参数用于获取转换错误时的详细错误信息
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = nullptr)
然后可以判断是否是object或者array:
bool isArray() const
bool isObject() const
最后可以通过object和array方法取得QJsonObject或者QJsonArray对象:
QJsonObject object() const
QJsonArray array() const
举例:
auto jsonDocument = QJsonDocument::fromJson("{\"name\":\"XiaoMing\",\"age\":12}");
auto jsonObj = jsonDocument.object();
qDebug().noquote() << QJsonDocument(jsonObj).toJson();
输出:
{
"age": 12,
"name": "XiaoMing"
}
总结
了解完上面这些内容,日常使用QJson应该没有问题了。
由于篇幅原因,其实还有很多东西没有提到,大家可以在QtCreater的帮助界面浏览各个类的详细信息,或者直接阅读源代码。
题外话:今天本来想看看源码找出QJsonObject为啥会按键排序,结果没找到,连用什么数据结构存储键值对数据都没找到,惭愧(只看到下面可能有个大数组),如果有大佬知道,求指点,多谢。