QJson是Qt中做Json传输的一个类库,可以从我的资源里下载到,QJson的中文主页在这里。
下载的时候,强烈建议你用git,从gitorious上下载,而不要用http下载gzip压缩包(因为我下载的版本的gzip压缩包里少pro文件件,而且CMake的配置文件也是错的……)!否则你可能在自己编译的时候走弯路。
QJson的一个例程在这里:
在Qt中如何通过QJson 解析json数据
注意,如果要让例程中的QJson使用中文,而不出乱码,那么,应该把main.cpp的第23-第24行改为:
- QString query = "[{\"我的rid\":\"房间号\", \"pid\":\"1000\", \"username\":\"可微\"},{\"rid\":\"000\", \"pid\":\"10200\", \"username\":\"dxy2\"}]";
- QVariant result = parser.parse(query.toUtf8(), &ok);
也就是把原来的toAscii改成toUtf8~
用C++生成Json字符串(使用时需要#include "Serializer.h"参见:http://www.oschina.net/code/snippet_12_333):
- QVariantList people;
-
- QVariantMap bob;
- bob.insert("Name", "Bob");
- bob.insert("Phonenumber", 123);
-
- QVariantMap alice;
- alice.insert("Name", "Alice");
- alice.insert("Phonenumber", 321);
-
- people << bob << alice;
-
- QJson::Serializer serializer;
- QByteArray json = serializer.serialize(people);
- qDebug() << json;
输出:
- "[ { "Name" : "Bob", "Phonenumber" : 123 },
- { "Name" : "Alice", "Phonenumber" : 321 } ]"
如果people中含有中文,则serialize之后,会出现乱码,解决方法参见:
http://my3d.sinaapp.com/?p=136
有两种方法:
1、改变Qt的字符编码格式
- QTextCodec *codec = QTextCodec::codecForName(“GB18030″);
- QTextCodec::setCodecForLocale(codec);
- QTextCodec::setCodecForCStrings(codec);
- QTextCodec::setCodecForTr(codec);
2、把serialize的返回值使用Unicode解码
- QTextCodec *tc = QTextCodec::codecForName(“UTF-8″);
-
- QJson::Serializer serializer;
- QByteArray json =serializer.serialize(expand);
-
- QString jsonstr=tc->toUnicode(json);
- qDebug()<<"json:"+jsonstr;
我只试过第二种,确实可行!
第二种方法做的事情比较微妙:
首先,请相信,serialize函数返回的确实是unicode字符,确切的说,是用UTF-8编码的Unicode字符,tc->toUnicode(json)是把用UTF-8编码的json转换成Unicode字符串,这不是多此一举吗?我不可以使用QString(const QByteArray&)构造一个Unicode字符串吗?
有些情况下可以!
看QString(const QByteArray&)的文档描述:
- QString::QString ( const QByteArray & ba )
-
- Constructs a string initialized with the byte array ba.The given byte array is converted to Unicode using fromAscii(). Stops copying at the first 0 character, otherwise copies the entire byte array.
-
- You can disable this constructor by defining QT_NO_CAST_FROM_ASCII when you compile your applications. This can be useful if you want to ensure that all user-visible strings go through QObject::tr(), for example.
该构造函数会对ba里的内容使用fromAscii()函数解码,fromAscii()是干什么的?如果你碰巧使用QTextCodec::setCodecForCStrings()设置了字符串的编码格式,如QTextCodec::setCodecForCStrings("GB2312")(就像我一样……),那么fromAscii()就会认为ba里的内容是GB2312编码过的,所以fromAscii()函数就是尝试使用GB2312对ba里的内容解码,然后将解码后的内容重新编码为UTF-8格式!错误就这样悄无声息地发生了~
而tc->toUnicode(json)则直接认为json里的内容是UTF-8的(本来就是这样的,不是吗?),让后直接用json里的内容生成字符串,然后就正确了~
结论是:如果你QTextCodec::setCodecForCStrings("UTF-8"),那么QString(const QByteArray&)和tc->toUnicode(json)的效果是一样的;否则QString(const QByteArray&)会产生乱码,tc->toUnicode(json)会返回正确的字符串,不含乱码的那种~
微妙吧~
第一种方法可行的原因是,Unicode是GB18030的一个真子集!就像ASCII是Unicode的一个真子集一样,所以不管用Unicode怎样对ASCII编码解码,总是对的,因为Unicode完美兼容ASCII!
用Json字符串生成C++里的变量(这是本文开始提到的那个例程里的main.cpp里的代码,使用时需要#include "parser.h"):
- QJson::Parser parser;
- bool ok;
-
- QString query = "[{\"我的rid\":\"房间号\", \"pid\":\"1000\", \"username\":\"可微\"},{\"rid\":\"000\", \"pid\":\"10200\", \"username\":\"dxy2\"}]";
- QVariant result = parser.parse(query.toUtf8(), &ok);
-
- QVariantList mylist = result.toList();
-
- foreach (QVariant plugin, mylist) {
- QVariantMap mymap = plugin.toMap();
- qDebug() << "[" << mymap["我的rid"].toString() << mymap["pid"].toString() << mymap["username"].toString() << "]";
- }