QT中Json的使用方法(类和json字符串相互转换的方法)

66 篇文章 12 订阅
36 篇文章 13 订阅

在QT5.0版本以后支持对Json的使用,直接使用QT提供的json类进行数据的组织和解析。

Json类介绍
QJsonDoucument它封装了一个完整的 JSON 文档,并且可以从 UTF-8 编码的基于文本的表示以及 Qt 自己的二进制格式读取和写入该文档。
QJsonArrayJSON 数组是一个值列表。可以通过从数组中插入和删除 QJsonValue 来操作该列表。
QJsonObjectJSON 对象是键值对的列表,其中键是唯一的字符串,值由 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 读出存储在对象中的数据。

/**************************************************************************

Qt中处理json和cJSON

JSON是一种轻量级的数据交换格式。

那么如何在Qt中处理json?首先要知道四个类。

第一个类QJsonDocument;

  把JSON格式的字符串转换成JSON对象/数组;或者把JSON对象/数组转换成JSON格式字符串。

第二个类QJsonObject;

  处理Json对象,{  }

第三个类QJsonArray;

  处理Json数组,[]

第四个类QjsonValue;

  可以是字符串、整型、布尔、浮点、json对象、json数组...

1、组织JSON数据写入磁盘

 1     QJsonObject obj;   //定义空对象
 2     QJsonObject sub;
 3     sub.insert("IP",QJsonValue("192.168.31.33"));//插入键值对
 4     sub.insert("Port",QJsonValue("9999"));
 5     obj.insert("server",QJsonValue(sub));
 6 
 7     QJsonDocument doc(obj);
 8     QByteArray data=doc.toJson();
 9     QFile file("tem1.json");
10     file.open(QIODevice::WriteOnly);
11     file.write(data);
12     file.close();

server:{

    IP:192.168.31.33,

    Port:9999

    }

2、把磁盘中JSON数据加载到内存

 1     QFile file("tem.json");
 2     file.open(QIODevice::ReadOnly);
 3     QByteArray data = file.readAll();
 4     file.close();
 5 
 6     QJsonDocument doc =QJsonDocument::fromJson(data);
 7     if(doc.isObject())
 8     {
 9         QJsonObject obj =doc .object();
10         QJsonValue  value=obj.value("server");
11         if(value.isObject())
12         {
13             QJsonObject sub=value.toObject();
14             QString IP = sub.value("IP").toString();
15             QString Port = sub.value("Port").toString();
16         }
17     }

   cJSON为我们提供一套操作json数据格式的API

  1、组织一个json数据格式的字符串写入磁盘

//创建一个json数组
cJSON *cJSON_CreateArray(void);
//创建一个json对象
cJSON *cJSON_CreateObject(void);
//向json数组种添加数据成员
void cJSON_AddItemToArray(cJSON *array, cJSON *item);
 //往json对象中添加数据成员
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
//把其他类型转换成cjson*
cJSON *cJSON_CreateNumber(double num);
cJSON *cJSON_CreateString(const char *string);
 /* These utilities create an Array of count items. */
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 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include<unistd.h>
  5 #include<sys/stat.h>
  6 #include<sys/types.h>
  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;          /* The item's string, if type==cJSON_String */
     int valueint;               /* The item's number, if type==cJSON_Number */
     double valuedouble;         /* The item's number, if type==cJSON_Number */
 
     char *string;               /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
 } 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数据如下
     {
         userName:xxxx,
         firstPwd:xxx,
         email:xxx
     }
     */
 
//解析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字符串互转)

  1. {
  2. "name": "布衣食",
  3. "gender": "Male",
  4. "age": 25,
  5. "attribute": {
  6. "skill": "Programming",
  7. "languages": [ "C", "C++", "Java" ],
  8. "frameworks": [ "Qt", "Android" ]
  9. }
  10. }

我希望把它转换为一个Programmer对象,Programmer的声明如下

Programmer.h

  1. #ifndef PROGRAMMER_H
  2. #define PROGRAMMER_H
  3. #include <QString>
  4. #include <QList>
  5. class Programmer
  6. {
  7. public:
  8. class Attribute
  9. {
  10. public:
  11. Attribute(const QString &skill, const QList<QString> &languages, const QList<QString> &frameworks);
  12. const QString &getSkill() const;
  13. const QList<QString> &getLanguages() const;
  14. const QList<QString> &getFrameworks() const;
  15. private:
  16. QString skill;
  17. QList<QString> languages;
  18. QList<QString> frameworks;
  19. };
  20. Programmer(const QString &name, const QString &gender, int age, Attribute attribute);
  21. const QString &getName() const;
  22. const QString &getGender() const;
  23. int getAge() const;
  24. const Attribute &getAttribute() const;
  25. QString toJson() const;
  26. static Programmer fromJson(const QString &json);
  27. private:
  28. QString name;
  29. QString gender;
  30. int age;
  31. Attribute attribute;
  32. };
  33. #endif // PROGRAMMER_H

在Java中,使用第三方库GSON就可以方便地实现对象和json之间的转换;而C++没有反射机制,所以没有类似的库。

于是,我只好自行编写转换代码,如下

将json转换为Programmer对象

  1. Programmer Programmer::fromJson(const QString &json)
  2. {
  3. QJsonParseError error;
  4. const QJsonDocument &document = QJsonDocument::fromJson(json.toUtf8(), &error);
  5. if (QJsonParseError::NoError == error.error)
  6. {
  7. const QJsonObject &programmerObject = document.object();
  8. const QString &name = programmerObject.value(QStringLiteral("name")).toString();
  9. const QString &gender = programmerObject.value(QStringLiteral("gender")).toString();
  10. int age = programmerObject.value(QStringLiteral("age")).toInt();
  11. const QJsonObject &attributeObject = programmerObject.value(QStringLiteral("attribute")).toObject();
  12. const QString &skill = attributeObject.value(QStringLiteral("skill")).toString();
  13. const QJsonArray &languagesArray = attributeObject.value(QStringLiteral("languages")).toArray();
  14. QList<QString> languages;
  15. for (const QJsonValue &value : languagesArray)
  16. {
  17. languages.append(value.toString());
  18. }
  19. const QJsonArray &frameworksArray = attributeObject.value(QStringLiteral("frameworks")).toArray();
  20. QList<QString> frameworks;
  21. for (const QJsonValue &value : frameworksArray)
  22. {
  23. frameworks.append(value.toString());
  24. }
  25. return Programmer(name, gender, age, Attribute(skill, languages, frameworks));
  26. }
  27. throw error.errorString();
  28. }

将Programmer对象转换为json

  1. QString Programmer::toJson() const
  2. {
  3. QJsonObject programmerObject;
  4. programmerObject.insert(QStringLiteral("name"), name);
  5. programmerObject.insert(QStringLiteral("gender"), gender);
  6. programmerObject.insert(QStringLiteral("age"), age);
  7. QJsonObject attributeObject;
  8. attributeObject.insert(QStringLiteral("skill"), attribute.getSkill());
  9. QJsonArray languagesArray;
  10. for (const QString &s : attribute.getLanguages())
  11. {
  12. languagesArray.append(s);
  13. }
  14. attributeObject.insert(QStringLiteral("languages"), languagesArray);
  15. QJsonArray frameworksArray;
  16. for (const QString &s : attribute.getFrameworks())
  17. {
  18. frameworksArray.append(s);
  19. }
  20. attributeObject.insert(QStringLiteral("frameworks"), frameworksArray);
  21. programmerObject.insert(QStringLiteral("attribute"), attributeObject);
  22. return QJsonDocument(programmerObject).toJson();
  23. }

编写这样的代码,枯燥费时,但我目前没有更好的解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值