在QT5.0版本以后支持对Json的使用,直接使用QT提供的json类进行数据的组织和解析。
| Json类 | 介绍 |
|---|---|
| QJsonDoucument | 它封装了一个完整的 JSON 文档,并且可以从 UTF-8 编码的基于文本的表示以及 Qt 自己的二进制格式读取和写入该文档。 |
| QJsonArray | JSON 数组是一个值列表。可以通过从数组中插入和删除 QJsonValue 来操作该列表。 |
| QJsonObject | JSON 对象是键值对的列表,其中键是唯一的字符串,值由 QJsonValue 表示。 |
| QJsonValue | 该类封装了 JSON 支持的数据类型。 |
1. QJsonValue
在 Qt 中 QJsonValue 可以封装的基础数据类型有六种(和 Json 支持的类型一致),分别为:
布尔类型:QJsonValue::Bool
浮点类型(包括整形): QJsonValue::Double
字符串类型: QJsonValue::String
Json 数组类型: QJsonValue::Array
Json 对象类型:QJsonValue::Object
空值类型: QJsonValue::Null
如何存取数据呢?
存:
使用这个对象可以封装这六种类型的数据:
// Json对象 QJsonValue(const QJsonObject &o); // Json数组 QJsonValue(const QJsonArray &a); // 字符串 QJsonValue(const char *s); QJsonValue(QLatin1String s); QJsonValue(const QString &s); // 整形 and 浮点型 QJsonValue(qint64 v); QJsonValue(int v); QJsonValue(double v); // 布尔类型 QJsonValue(bool b); // 空值类型 QJsonValue(QJsonValue::Type type = Null);
取:
使用相关的判断函数判断该数据的类型:
// 是否是Json数组 bool isArray() const; // 是否是Json对象 bool isObject() const; // 是否是布尔类型 bool isBool() const; // 是否是浮点类型(整形也是通过该函数判断) bool isDouble() const; // 是否是空值类型 bool isNull() const; // 是否是字符串类型 bool isString() const; // 是否是未定义类型(无法识别的类型) bool isUndefined() const;
判断出数据类型以后就可以转换为实际的基础数据类型
// 转换为Json数组 QJsonArray toArray(const QJsonArray &defaultValue) const; QJsonArray toArray() const; // 转换为布尔类型 bool toBool(bool defaultValue = false) const; // 转换为浮点类型 double toDouble(double defaultValue = 0) const; // 转换为整形 int toInt(int defaultValue = 0) const; // 转换为Json对象 QJsonObject toObject(const QJsonObject &defaultValue) const; QJsonObject toObject() const; // 转换为字符串类型 QString toString() const; QString toString(const QString &defaultValue) const;
2. QJsonObject
QJsonObject 封装了 Json 中的对象,在里边可以存储多个键值对,为了方便操作,键值为字符串类型,值为 QJsonValue 类型。关于这个类的使用类似于 C++ 中的 STL 类,仔细阅读 API 文档即可熟练上手使用,下面介绍一些常用 API 函数:
如何创建空的 Json 对象
QJsonObject::QJsonObject(); // 构造空对象
将键值对添加到空对象中
iterator QJsonObject::insert(const QString &key, const QJsonValue &value);
获取对象中键值对个数
int QJsonObject::count() const; int QJsonObject::size() const; int QJsonObject::length() const;
通过 key 得到 value
QJsonValue QJsonObject::value(const QString &key) const; // utf8 QJsonValue QJsonObject::value(QLatin1String key) const; // 字符串不支持中文 QJsonValue QJsonObject::operator[](const QString &key) const; QJsonValue QJsonObject::operator[](QLatin1String key) const;
删除键值对
void QJsonObject::remove(const QString &key); QJsonValue QJsonObject::take(const QString &key); // 返回key对应的value值
通过key进行查找
iterator QJsonObject::find(const QString &key); bool QJsonObject::contains(const QString &key) const;
遍历,方式有三种:
使用相关的迭代器函数
使用 [] 的方式遍历,类似于遍历数组,[] 中是键值
先得到对象中所有的键值,在遍历键值列表,通过 key 得到 value 值
QStringList QJsonObject::keys() const;
3. QJsonArray
QJsonArray 封装了 Json 中的数组,在里边可以存储多个元素,为了方便操作,所有的元素类统一为 QJsonValue 类型。也类似C++中的STL类。
创建空的 Json 数组
QJsonArray::QJsonArray();
添加数据
void QJsonArray::append(const QJsonValue &value); // 在尾部追加 void QJsonArray::insert(int i, const QJsonValue &value); // 插入到 i 的位置之前 iterator QJsonArray::insert(iterator before, const QJsonValue &value); void QJsonArray::prepend(const QJsonValue &value); // 添加到数组头部 void QJsonArray::push_back(const QJsonValue &value); // 添加到尾部 void QJsonArray::push_front(const QJsonValue &value); // 添加到头部
计算数组元素的个数
int QJsonArray::count() const; int QJsonArray::size() const;
从数组中取出某一个元素的值
QJsonValue QJsonArray::at(int i) const; QJsonValue QJsonArray::first() const; // 头部元素 QJsonValue QJsonArray::last() const; // 尾部元素 QJsonValueRef QJsonArray::operator[](int i);
删除数组中的某一个元素
iterator QJsonArray::erase(iterator it); // 基于迭代器删除 void QJsonArray::pop_back(); // 删除尾部 void QJsonArray::pop_front(); // 删除头部 void QJsonArray::removeAt(int i); // 删除i位置的元素 void QJsonArray::removeFirst(); // 删除头部 void QJsonArray::removeLast(); // 删除尾部 QJsonValue QJsonArray::takeAt(int i); // 删除i位置的原始, 并返回删除的元素的值
Josn 数组的遍历,常用的方式有两种:
可以使用迭代器进行遍历(和使用迭代器遍历 STL 容器一样)
可以使用数组的方式遍历
4. QJsonDocument
它封装了一个完整的 JSON 文档,并且可以从 UTF-8 编码的基于文本的表示以及 Qt 自己的二进制格式读取和写入该文档。QJsonObject 和 QJsonArray 这两个对象中的数据是不能直接转换为字符串类型的,如果要进行数据传输或者数据的持久化,操作的都是字符串类型而不是 QJsonObject 或者 QJsonArray 类型,我们需要通过一个 Json 文档类进行二者之间的转换。
这就好比你所有的操作都完成,就差最后一步存储到本地磁盘,那这一步怎么做呢?
下面依次介绍一下这两个转换流程应该如何操作:
(1)、创建 QJsonDocument 对象
QJsonDocument::QJsonDocument(const QJsonObject &object); QJsonDocument::QJsonDocument(const QJsonArray &array);
这个函数的作用就是将JSON数组和对象转换成一个QJsonDocument对象。
(2)将文件对象中的数据进行序列化
// 二进制格式的json字符串 QByteArray QJsonDocument::toBinaryData() const; // 文本格式 QByteArray QJsonDocument::toJson(JsonFormat format = Indented) const;
再通过调用 toxxx() 方法就可以得到文本格式或者二进制格式的 Json 字符串了。
(3)使用得到的字符串进行数据传输,或者磁盘文件持久化
字符串 ===> QJsonObject 或者 QJsonArray
一般情况下,通过网络通信或者读磁盘文件就会得到一个 Json 格式的字符串,如果想要得到相关的原始数据就需要对字符串中的数据进行解析,具体解析流程如下:
(1)将得到的 Json 格式字符串通过 QJsonDocument 类的静态函数转换为 QJsonDocument 类对象
[static] QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation = Validate); // 参数文件格式的json字符串 [static] QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error = Q_NULLPTR);
(2)将文档对象转换为 json 数组 / 对象
// 判断文档对象中存储的数据是不是数组
bool QJsonDocument::isArray() const;
// 判断文档对象中存储的数据是不是json对象
bool QJsonDocument::isObject() const
// 文档对象中的数据转换为json对象
QJsonObject QJsonDocument::object() const;
// 文档对象中的数据转换为json数组
QJsonArray QJsonDocument::array() const;
(3)通过调用 QJsonArray , QJsonObject 类提供的 API 读出存储在对象中的数据。
cJSON *cJSON_CreateIntArray(const int *numbers,int count); cJSON *cJSON_CreateFloatArray(const float *numbers,int count); cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); cJSON *cJSON_CreateStringArray(const char **strings,int count);
一个小demo
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include"cJSON.h" 8 int main() 9 { 10 //创建一个json对象 11 cJSON *obj = cJSON_CreateObject(); 12 //创建一个子对象 13 cJSON *subobj= cJSON_CreateObject(); 14 //往子对象中添加键值 15 cJSON_AddItemToObject(subobj,"type",cJSON_CreateString("章回体古装喜剧")); 16 cJSON_AddItemToObject(subobj,"director",cJSON_CreateString("尚敬")); 17 cJSON_AddItemToObject(subobj,"year",cJSON_CreateNumber(2006)); 18 cJSON *arry = cJSON_CreateArray(); 19 cJSON_AddItemToArray(arry,cJSON_CreateString("闫妮")); 20 cJSON_AddItemToArray(arry,cJSON_CreateString("沙益")); 21 cJSON_AddItemToArray(arry,cJSON_CreateString("姚晨")); 22 cJSON_AddItemToArray(arry,cJSON_CreateString("喻恩泰")); 23 cJSON_AddItemToArray(arry,cJSON_CreateNumber(123)); 24 25 cJSON *subsub = cJSON_CreateObject(); 26 cJSON_AddItemToObject(subsub,"天热了睡凉席",cJSON_CreateString("天冷了加件衣")); 27 cJSON_AddItemToArray(arry,subsub); 28 cJSON_AddItemToObject(subobj,"other",arry); 29 //往对象中添加键值对 30 cJSON_AddItemToObject(obj,"武林外传",subobj); 31 //把json转换成字符串,方便写入磁盘 32 char *data = cJSON_Print(obj); 33 FILE *fd = fopen("cjson.cj","w"); 34 fwrite(data,1,strlen(data)+1,fd); 35 fclose(fd); 36 return 0; 37 }
{
"武林外传": {
"type": "章回体古装喜剧",
"director": "尚敬",
"year": 2006,
"other": ["闫妮", "沙益", "姚晨", "喻恩泰", 123, {
"天热了睡凉席": "天冷了加件衣"
}]
}
2、解析json,获取值
//cJSON结构体
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON;
//解析一个json字符串为cJSON对象
cJOSN * cJSON_Parse(const char*buf);
//根据键查找值
cJSON * cJSON_GetObjectItem(cJSON*obj,const char *key);
一个demo
void get_reg_info(char *reg_buf, char *user, char *pwd,char *email)
{
//解析json包
//解析一个json字符串为cJSON对象
cJSON * root = cJSON_Parse(reg_buf);
if(NULL == root)
{
//出错处理
}
//返回指定字符串对应的json对象
//用户
cJSON *child1 = cJSON_GetObjectItem(root, "userName");
if(NULL == child1)
{
//出错处理
}
strcpy(user, child1->valuestring);
cJSON *child2=cJSON_GetObjectItem(root,"fristPwd");
if(NULL ==child2)
{}
strcpy(pwd,child2->valuestring);
cJSON *child2 = cJSON_GetObjectItem(root,"email");
strcpy(email,child2->valuestring);
cJSON_Delete(root);
}
/***************************
把JSON转成一个类对象(类与json字符串互转)- {
- "name": "布衣食",
- "gender": "Male",
- "age": 25,
- "attribute": {
- "skill": "Programming",
- "languages": [ "C", "C++", "Java" ],
- "frameworks": [ "Qt", "Android" ]
- }
- }
我希望把它转换为一个Programmer对象,Programmer的声明如下
Programmer.h
- #ifndef PROGRAMMER_H
- #define PROGRAMMER_H
- #include
- #include
- class Programmer
- {
- public:
- class Attribute
- {
- public:
- Attribute(const QString &skill, const QList
&languages, const QList &frameworks); - const QString &getSkill() const;
- const QList
&getLanguages() const; - const QList
&getFrameworks() const; - private:
- QString skill;
- QList
languages; - QList
frameworks; - };
- Programmer(const QString &name, const QString &gender, int age, Attribute attribute);
- const QString &getName() const;
- const QString &getGender() const;
- int getAge() const;
- const Attribute &getAttribute() const;
- QString toJson() const;
- static Programmer fromJson(const QString &json);
- private:
- QString name;
- QString gender;
- int age;
- Attribute attribute;
- };
- #endif // PROGRAMMER_H
在Java中,使用第三方库GSON就可以方便地实现对象和json之间的转换;而C++没有反射机制,所以没有类似的库。
于是,我只好自行编写转换代码,如下
将json转换为Programmer对象
- Programmer Programmer::fromJson(const QString &json)
- {
- QJsonParseError error;
- const QJsonDocument &document = QJsonDocument::fromJson(json.toUtf8(), &error);
- if (QJsonParseError::NoError == error.error)
- {
- const QJsonObject &programmerObject = document.object();
- const QString &name = programmerObject.value(QStringLiteral("name")).toString();
- const QString &gender = programmerObject.value(QStringLiteral("gender")).toString();
- int age = programmerObject.value(QStringLiteral("age")).toInt();
- const QJsonObject &attributeObject = programmerObject.value(QStringLiteral("attribute")).toObject();
- const QString &skill = attributeObject.value(QStringLiteral("skill")).toString();
- const QJsonArray &languagesArray = attributeObject.value(QStringLiteral("languages")).toArray();
- QList
languages; - for (const QJsonValue &value : languagesArray)
- {
- languages.append(value.toString());
- }
- const QJsonArray &frameworksArray = attributeObject.value(QStringLiteral("frameworks")).toArray();
- QList
frameworks; - for (const QJsonValue &value : frameworksArray)
- {
- frameworks.append(value.toString());
- }
- return Programmer(name, gender, age, Attribute(skill, languages, frameworks));
- }
- throw error.errorString();
- }
将Programmer对象转换为json
- QString Programmer::toJson() const
- {
- QJsonObject programmerObject;
- programmerObject.insert(QStringLiteral("name"), name);
- programmerObject.insert(QStringLiteral("gender"), gender);
- programmerObject.insert(QStringLiteral("age"), age);
- QJsonObject attributeObject;
- attributeObject.insert(QStringLiteral("skill"), attribute.getSkill());
- QJsonArray languagesArray;
- for (const QString &s : attribute.getLanguages())
- {
- languagesArray.append(s);
- }
- attributeObject.insert(QStringLiteral("languages"), languagesArray);
- QJsonArray frameworksArray;
- for (const QString &s : attribute.getFrameworks())
- {
- frameworksArray.append(s);
- }
- attributeObject.insert(QStringLiteral("frameworks"), frameworksArray);
- programmerObject.insert(QStringLiteral("attribute"), attributeObject);
- return QJsonDocument(programmerObject).toJson();
- }
编写这样的代码,枯燥费时,但我目前没有更好的解决方案。



