# 【Qt编程】基于Qt的词典开发系列--JSON数据解析
在上一篇文章《[用户登录及API调用的实现](http://blog.csdn.net/tengweitw/article/details/45932429)》中,我通过程序实现了用户登录及API调用的实现,从而能够实现网络查词、添词的操作。但是,从上文中可以看到,调用API后返回的是JSON格式的数据,如下图所示(在QtCreator中的显示):
![](https://box.kancloud.cn/2016-01-15_5698c1c86f5d8.jpg)
为了更好的观察JSON格式,我整理后显示如下:
![](https://box.kancloud.cn/2016-01-15_5698c1c87fa2a.jpg)
显然,为了显示查词的结果,我们必须在上图中提取有用的信息,并正确的显示出来。上图中每一行内容的意思我已经在文章《[调用网络API](http://blog.csdn.net/tengweitw/article/details/45484803)》中作了解释。我在词典中选择想要显示的内容有:单词本身、单词ID、中文解释、英文解释、音标、发音音频,与之对应上图中的content、learning_id、definition、en_definitions、pron、audio。
为了获取这些内容,我们必须进行对上面的JSON格式数据(关于什么是JSON格式,可以自己百度)进行解析。在Qt 4中,没有对应的模块,必须单独加入相应的函数库,当然也可以自己根据JSON的格式自己写程序提取你想要的内容,只不过比较麻烦而已。在Qt5中,自带有对应的JSON解析模块,因此不用自己来写解析函数了,只需要调用相应的函数。**下面给出具体的程序实现:**
程序的主体框架与文章《[用户登录及API调用的实现](http://blog.csdn.net/tengweitw/article/details/45932429)》中的一样,只是在其中加入了JSON数据解析功能。具体的说,每当发送查词请求后,服务器就会返回JSON格式的单词内容。因此,我们只需要在处理服务器返回数据的函数replyfinished()函数中对应的查词操作QueryWordAction中进行JSON数据解析,将我们需要的内容存储到我们定义的Word类中。其中,word的定义如下:
![](https://box.kancloud.cn/2016-01-15_5698c1c89334c.jpg)
由于只是在上文《[用户登录及API调用的实现](http://blog.csdn.net/tengweitw/article/details/45932429)》的程序中加了JSON解析的部分,其它部分基本没变,所以程序的运行流程及思路可见上文。当然,程序中的注释也算比较详细,因此不作具体说明。只需要将下面五个源文件放入空的Qt项目中即可。注意:是在Qt 5中,且需要在其.pro文件中加入语句:QT +=core gui network webkit multimedia。**具体的源文件如下**:
* * *
**1、word.h文件**
~~~
#ifndef WORD_H
#define WORD_H
#include<QString>
#include<List>
#include <QJsonObject>
#include<QtMultimedia/QMediaPlayer>
#include<QUrl>
class Word
{
public:
explicit Word();
Word(const Word& word);
~Word();
public:
QString name;//单词本身
QString learning_id;//单词ID
QString definition;//单词中文解释
QString en_definitions;//单词英文解释
QString pron;//单词音标
QString audio;//单词的发音音频
void clear();
};
#endif // WORD_H
~~~
* * *
**2、word.cpp文件**
~~~
#include "word.h"
Word::Word()
{
}
Word::Word(const Word &w)
{
name=w.name;
learning_id=w.learning_id;
definition=w.definition;
en_definitions=w.en_definitions;
pron=w.pron;
audio=w.audio;
}
Word::~Word()
{
}
void Word::clear()//清除内容
{
name="";
learning_id="";
definition="";
en_definitions="";
pron="";
audio="";
// this->examples=NULL;
}
~~~
* * *
**3、network.h文件**
~~~
#ifndef NETWORK_H
#define NETWORK_H
#include"word.h"
#include <QObject>
#include <QtNetwork/QNetworkAccessManager>
#include<QtNetwork/QNetworkReply>
#include<QtNetwork/QNetworkRequest>
#include<QtNetwork/QNetworkCookie>
#include<QtNetwork/QNetworkCookieJar>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include<QString>
#include<QDebug>
#include<QList>
#include<QUrl>
#include<QByteArray>
class netWork : public QObject
{
Q_OBJECT
public:
explicit netWork(QObject *parent = 0);
// ~netWork();
enum HttpAction{NoAction,NetStudy,GetSessionidAction,LoginAction,QueryWordAction,AddWordAction,AddExampleAction,QueryWordExamplesAction};
HttpAction httpAction;
QNetworkAccessManager * http;
QString sessionid;
QString queryword;//要查询的单词
QString nickname;
QString username;
QString password;
bool isBusy;
Word *gotword;//通过访问网络得到的单词信息
QString getCookie(const QString &name);
void loginShanbay();
void queryWord(const QString &word);
void queryExamples(QString learningid);
void connectNet(QString username="nineheadedbird", QString password="123456");
void addWord(const QString &word);
signals:
void signalQueryFinished(Word *word);
void connectSuccess();
void connectFail();
void verifySuccess();
void verifyFail();
void NetState(bool);
public slots:
void replyfinished(QNetworkReply*);
};
#endif // NETWORK_H
~~~
* * *
**4、network.cpp文件**
~~~
#include "network.h"
#include<QList>
#include<QDesktopServices>
netWork::netWork(QObject *parent) :
QObject(parent)
{
http=new QNetworkAccessManager(this);
http->setCookieJar(new QNetworkCookieJar(this));
connect(http,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyfinished(QNetworkReply*)));
isBusy=true;
gotword=new Word();
}
QString netWork::getCookie(const QString &name)
{
foreach(QNetworkCookie cookie , http->cookieJar()->cookiesForUrl(QUrl("http://www.shanbay.com/")))
{
//qDebug()<<cookie.name();
if(cookie.name()==name)
{
return cookie.value();
}
}
return "";
}
void netWork::loginShanbay()
{
QNetworkRequest request;
request.setUrl(QUrl("http://www.shanbay.com/accounts/login/"));
request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3");
request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8");
request.setRawHeader("Cache-Control","max-age=0");
request.setRawHeader("Connection","keep-alive");
request.setRawHeader("Host","www.shanbay.com");
request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7");
request.setRawHeader("Origin","http//www.shanbay.com");
request.setRawHeader("Referer","http://www.shanbay.com/accounts/login/");
request.setRawHeader("Host","www.shanbay.com");
request.setRawHeader("Content-Type","application/x-www-form-urlencoded");
QByteArray postData;
postData.append(QString("csrfmiddlewaretoken=%1&").arg(sessionid));
postData.append(QString("username=%1&password=%2&").arg(QUrl::toPercentEncoding(username).constData()).arg(password));
postData.append("login=登录&continue=home&u=1&next=");
request.setHeader(QNetworkRequest::ContentLengthHeader,postData.size());
httpAction=LoginAction;
http->post(request,postData);
}
void netWork::queryWord(const QString &word)
{
QNetworkRequest request;
request.setUrl(QUrl("http://www.shanbay.com/api/word/"+word));
request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3");
request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8");
request.setRawHeader("Cache-Control","max-age=0");
request.setRawHeader("Connection","keep-alive");
request.setRawHeader("Host","www.shanbay.com");
request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7");
httpAction=QueryWordAction;
http->get(request);
}
void netWork::queryExamples(QString learningid)
{
if(learningid=="0"){
return;
}
QNetworkRequest request;
request.setUrl(QUrl("http://www.shanbay.com/api/learning/examples/"+learningid));
request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3");
request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8");
request.setRawHeader("Cache-Control","max-age=0");
request.setRawHeader("Connection","keep-alive");
request.setRawHeader("Host","www.shanbay.com");
request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7");
httpAction=QueryWordExamplesAction;
http->get(request);
}
void netWork::addWord(const QString &word)
{
if(word.isEmpty())
qDebug()<<"你的输入有误";
else
{
QNetworkRequest request;
request.setUrl(QUrl("http://www.shanbay.com/api/learning/add/"+word));
request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3");
request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8");
request.setRawHeader("Cache-Control","max-age=0");
request.setRawHeader("Connection","keep-alive");
request.setRawHeader("Host","www.shanbay.com");
request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7");
httpAction=AddWordAction;
http->get(request);
}
}
void netWork::connectNet(QString username, QString password)
{
this->username=username;
this->password=password;
QNetworkRequest request;
request.setUrl(QUrl("http://www.shanbay.com/accounts/login/"));
request.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
request.setRawHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.3");
request.setRawHeader("Accept-Language","zh-CN,zh;q=0.8");
request.setRawHeader("Cache-Control","max-age=0");
request.setRawHeader("Connection","keep-alive");
request.setRawHeader("Host","www.shanbay.com");
request.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7");
httpAction=GetSessionidAction;
http->get(request);
}
void netWork::replyfinished(QNetworkReply *reply)
{
QByteArray wordInformation;
QVariant status_code=reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
// qDebug()<<"code_state="<<status_code;
if(status_code==QVariant::Invalid)
emit NetState(false);
else
emit NetState(true);
QJsonDocument jsonDoc;
QJsonObject jsonObj,vocObj,en_definitionsObj;
switch(httpAction)
{
case NoAction:
break;
case GetSessionidAction:
sessionid=getCookie("csrftoken");
if(!sessionid.isEmpty()){
emit connectSuccess();
qDebug()<<("Connect successfully! Verifying username and password...");
loginShanbay();
}else{
emit connectFail();
qDebug()<<("Cannot connect! Please try to check the internet!");
}
break;
case LoginAction:
httpAction=NoAction;
if(0==reply->readAll().size())
{
QString nickname=QUrl::fromPercentEncoding(getCookie("username").toLatin1());
emit verifySuccess();
qDebug()<<"Login successfully!"<<nickname;
queryWord("hello");
}else
{
emit verifyFail();
qDebug()<<"Failed to login! Please check!";
}
break;
case QueryWordAction://是在这里面进行JSON数据解析!
qDebug()<<"----query word----";
wordInformation=reply->readAll();
qDebug()<<"the information of word in JSON format::\n";
qDebug()<< wordInformation;
jsonDoc=QJsonDocument::fromJson( wordInformation);
if(!jsonDoc.isNull())
{
jsonObj=jsonDoc.object();
vocObj=jsonObj.value("voc").toObject();//Qt5 自带JSON解析,因此很容易得到单词的各个部分的内容
en_definitionsObj=vocObj.value("en_definitions").toObject();
gotword->clear();
gotword->name=vocObj.value("content").toString();//单词本身
gotword->learning_id=QString::number(jsonObj.value("learning_id").toDouble(),'g',15);
gotword->definition=vocObj.value("definition").toString();//中文解释
gotword->pron=vocObj.value("pron").toString();//单词音标
gotword->pron=gotword->pron;
gotword->audio=vocObj.value("audio").toString();
//由于单词的英文解释有多项(词性、解释等等),我们将结果用html格式表示,并使得词性颜色设置为黑色
for( QJsonObject::const_iterator it=en_definitionsObj.constBegin();it!=en_definitionsObj.constEnd();it++)
{
gotword->en_definitions+=QString("<br><font color='black'><b>%1\. </b></font>").arg(it.key());
if(it.value().isArray())
{
foreach(QJsonValue jv,it.value().toArray())
{
gotword->en_definitions+=QString("%1; ").arg(jv.toString());
}
}
gotword->en_definitions+="<br>";
}
emit signalQueryFinished(gotword);
//显示JSON解析后的数据
qDebug()<<"name="<<gotword->name;
qDebug()<<"word="<<gotword->learning_id;
qDebug()<<"definition="<<gotword->definition;
qDebug()<<"en_definitions="<<gotword->en_definitions;
qDebug()<<"pron="<<gotword->pron;
qDebug()<<"audio"<<gotword->audio;
//进行网络发音
QMediaPlayer *player = new QMediaPlayer();
player->setMedia(QUrl(gotword->audio));
player->play();
if(gotword->learning_id!="0")//不是新单词
{
qDebug()<<"你学过这个单词";
}
}
break;
case QueryWordExamplesAction:
// qDebug()<<"query word examples";
// qDebug()<<reply->readAll();
break;
case AddWordAction:
// qDebug()<<"add word";
jsonDoc=QJsonDocument::fromJson(reply->readAll());
if(!jsonDoc.isNull())
{
jsonObj=jsonDoc.object();
//qDebug()<<"jsonObj"<<jsonObj;
gotword->learning_id=QString::number(jsonObj.value("id").toDouble(),'g',15);
// qDebug()<<jsonObj.value("id").toDouble()<<"add word result learning id="<<gotword->learning_id<< (gotword->learning_id!="0");
// emit signalAddwordFinished(DICT::word->learning_id!="0");
// queryExamples(DICT::word->learning_id);
}
default:break;
}
}
~~~
* * *
**5、main.cpp文件**
~~~
#include <QApplication>
#include "network.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
netWork *nW = new netWork();
nW->connectNet();
return a.exec();
}
~~~
**运行结果如下图:**
![](https://box.kancloud.cn/2016-01-15_5698c1c8a3912.jpg)
- 前言
- <一>--词典框架设计及成品展示
- <二>--本地词典的设计
- <三>--开始菜单的设计
- <四>--无边框窗口的缩放与拖动
- <五>--无边框窗口的拖动
- <六>--界面美化设计
- <七>--调用网络API
- <八>--用户登录及API调用的实现
- <九>--JSON数据解析
- <十>--国际音标的显示
- <十一>系统托盘的显示
- <十二>调用讲述人
- <十三>音频播放
- <十四>自动补全功能
- <十五>html特殊字符及正则表达式
- 后序