QJson: a Qt-based library for mapping JSON data to QVariant objects
Posted by Flavio in C++, KDE, Programming, QtIn order to realize a project of mine I started looking for a Qt library for mapping JSON data to Qt objects.
I came over a couple of solutions but none of them made me happy. So in the last weekend I wrote my own library : QJson
The library is based on Qt toolkit and converts JSON data to QVariant instances.
JSON arrays will be mapped to QVariantList instances, while JSON’s objects will be mapped to QVariantMap.
The JSON parser is generated with Bison, while the scanner has been coded by me.
Usage
Converting JSON’s data to QVariant instance is really simple:
// create a JSonDriver instance JSonDriver driver; bool ok; // json is a QString containing the data to convert QVariant result = driver.parse (json, &ok);
Suppose you’re going to convert this JSON data:
{
“encoding” : “UTF-8″,
“plug-ins” : [
"python",
"c++",
"ruby"
],
“indent” : { “length” : 3, “use_space” : true }
}
The following code would convert the JSON data and parse it:
JSonDriver driver;
bool ok;
QVariantMap result = driver.parse (json, &ok).toMap();
if (!ok) {
qFatal("An error occured during parsing");
exit (1);
}
qDebug() << "encoding:" << result["encoding"].toString();
qDebug() << "plugins:";
foreach (QVariant plugin, result["plug-ins"].toList()) {
qDebug() << "\t-" << plugin.toString();
}
QVariantMap nestedMap = result["indent"].toMap();
qDebug() << "length:" << nestedMap["length"].toInt();
qDebug() << "use_space:" << nestedMap["use_space"].toBool();
The output would be:
encoding: “UTF-8″
plugins:
- “python”
- “c++”
- “ruby”
length: 3
use_space: true
Requirements
QJson requires:
- cmake
- Qt
Obtain the source
Actually QJson code is hosted on KDE subversion repository. You can download it using a svn client:
svn co svn://anonsvn.kde.org/home/kde/trunk/playground/libs/qjson
For more informations visit QJson site
Tags: C++, JSON, KDE, qjson, Qt














Entries (RSS)
Looks good, but did you look at http://www.fredemmott.co.uk/blog_161?
Maybe you could cooperate?
Before creating QJson I tried JsonQt. I discovered that it works only when receiving JSON objects and not arrays (if you try to map something like [50, "foo"] it reports a parsing error). I wanted to fix this problem but reading the code I discovered that Fred Emmott didn’t use a parser generator.
I think that using a parser generator can help a lot and so I came out with QJson.
Thanks a lot! I need this very functionality for a project a mine, but hadn’t got around to writing the code yet. The API I had in mind would work exactly the same as yours =) Thanks again!
Thanks for this library, it’s opening many technological doors ^^
I’m a lazy coder too …
You might like to also add ‘bison’ to your requirements list.
No Bison is not a requirement for the final developers. It’s needed just when the grammar file is changed, and this shouldn’t be done (unless JSON specs change or a bug in my parser is found).
All the files generated by Bison are shipped with QJson sources
Hi,
I’m using this code in a project of mine (as I was already suggesting above) and it is working great! I just discovered one bug though:
When you input a JSON string containing the following string: “\\n” (using C syntax, so that’s a single backslash and an n), you get this very string “\\n” in the QVariantMap. However, according to JSON.org, “\\n” is the official escape sequence for a newline, and so should be converted to “\n” (which is a newline character, still using C syntax).
If you do not translate “\\n” back to “\n”, it becomes impossible to do a two-way conversion from a QVariantMap with strings than contain newlines to JSON and back.
Hope I made it clear what I meant
Greetings,
Arend jr.
JSon grammar description reports:
char
any-Unicode-character-
except-”-or-\-or-
control-character
\”
\\
\/
\b
\f
\n
\r
\t
\u four-hex-digits
So the newline char is \n while \\ is just to be interpreted as the escaping of \
Take a look at the TestJSonDriver::testEscapeChars method.
Maybe I am wrong or I didn’t understand you, feel free to correct me.
Thanks for your reply!
I just took a look at the testEscapeChars method, and found this:
QString json = “[\"\b \f \n \r \t \", \" \\ \\/ \\\" \"]“;
QVariantList list;
list.append (QVariant(“\b \f \n \r \t “));
list.append (QVariant(” \\ \\/ \\\” “));
The JSON string you are using here as input is not valid from what I can tell, because “\n”, “\r”, etc. are not valid inside a JSON string. So these lines should IMHO become:
QString json = “[\"\\b \\f \\n \\r \\t \", \" \\\\ \\/ \\\" \"]“;
QVariantList list;
list.append (QVariant(“\b \f \n \r \t “));
list.append (QVariant(” \\ / \” “));
With these changes, I think the test should be correct.
Finally, here is the unescaping function I use now to properly unescape the strings:
QString unescapeJsonString(const QString &string) {
QString unescapedString;
unescapedString.reserve(string.length());
for (int i = 0; i < string.length(); i++) {
QChar character = string[i];
if (character == ‘\\’) {
if (i == string.length() – 1) {
qDebug() << “json_parser: Unfinished escape sequence!”;
break;
}
i++;
switch (string[i].unicode()) {
case ‘”‘:
unescapedString += ‘”‘;
break;
case ‘\\’:
unescapedString += ‘\\’;
break;
case ‘b’:
unescapedString += ‘\b’;
break;
case ‘f’:
unescapedString += ‘\f’;
break;
case ‘n’:
unescapedString += ‘\n’;
break;
case ‘r’:
unescapedString += ‘\r’;
break;
case ‘t’:
unescapedString += ‘\t’;
break;
default:
qDebug() << “json_parser.cc: Unrecognized escape sequence!”;
unescapedString += string[i];
break;
}
} else {
unescapedString += character;
}
}
return unescapedString;
}
Greetings,
Arend jr.
Thanks for the report Arend. I have fixed the scanner and I have updated the test code.
Now you shouldn’t need to use your function.
Feel free to contact me for clarifications.
PS.: The same goes for other control characters.
I found QJson doesn’t support Chinese.
Hey Flavio. I’m a bit new to Qt, and am having trouble using your library to grab data from a twitter feed. The json string goes like so:
[
{“user”:
{“followers_count”:100,”description”:”Google: nickhere”,”url”:”",”profile_image_url”:”",”protected”:false,”location”:”Austin, Texas”,”screen_name”:”nickhere”,”name”:”nickhere”,”id”:00000000},
“text”:”msghere”,
“truncated”:false,
“favorited”:false,
“in_reply_to_user_id”:null,
“created_at”:”Mon Mar 30 03:20:54 +0000 2009″,
“source”:”web”,
“in_reply_to_status_id”:null,
“id”:00000000000},
etc…
Do you think you could help me out? I looked through the documentation of QVariant, and QVariantMap, and am having no luck iterating through the parsed result. It doesn’t seem like there’s a QVariant::toArray(), which might be a better fit.
At any rate, thanks for taking a look.
First I managed to make a .pro file and build it on windows. Seems to work good. Thanks for your effort too.
One question though.
from json_driver.h
@param ok if a conversion error occurs, *ok is set to false; otherwise *ok is set to true.
and the example code says
# if (status) {
# qFatal(“An error occured during parsing”);
# exit (1);
# }
So is status being true is a error or not and error? The sample code runs things status is an error and exists, but it does not print any error info.
You should checkout latest version of QJson from SVN. I have committed lots of changes (and even more are coming).
Now the right syntax is
driver.parse(json, &ok);
if (!ok) {
qCritical(“we got an error!”);
}
I have updated the post reflecting this API change.
Thanks,
I am pretty sure that I had checked out the code from the svn repo last night. So it should be pretty latest?
Also, I am kinda not sure tieing QJson with a particular compiler and few platforms, does the compiler you prefered do something special?
I have commited new changes this morning (currently my timezone is GMT+1), so please check out the code.
The code is based on Qt, so I think that all compilers supported by Qt should work fine.
yes it does except that for some reason snprintf gives compiler error, (undefined) since it is a debuging instruction, I have commented that out.
Yes, I have checkout the latest few min back, things has changed.
Thanks.
Hi looks like snprintf is not a portable function, can you consider using QString::number instead?
I have removed snprintf from the code.
Numbers are stroed as QVariant::Int, which is incorrect, large numbers in the json file is returned as negative value, I guess it is logical that all numbers be just one type, Double or float.
fine.. thanks.
it’s great thanks!
[...] de las dependencias kopete-facebook es qjson, una librería que extiende Qt para añadirle un JSON Parser, necesario para procesar los datos [...]
Hi guys, I just want to know how to build QJson under windows, i’m using qt creator under vista.
I tried to use 1. shared lib and 2. simply import the source files to an existing GUI project, both didn’t work, I got error like this:
===
…../debug/moc_serializerrunnable.cpp:42: error: definition of static data member ‘SerializerRunnable::staticMetaObject’ of dllimport’d class
===
I just started to learn Qt, please help me…
And I also got a bunch of warnings like this:
===
…../serializer.cpp:36: warning: non-inline function ‘QJson::Serializer::~Serializer()’ is defined after prior declaration as dllimport: attribute ignored
===
Hi,
I get the following log/error when I try to run ‘Configure’ using Cmake (version 2.6 patch4)
The C compiler identification is GNU
The CXX compiler identification is GNU
Check for working C compiler: C:/Qt/2009.03/mingw/bin/gcc.exe
Check for working C compiler: C:/Qt/2009.03/mingw/bin/gcc.exe — works
Detecting C compiler ABI info
Detecting C compiler ABI info – done
Check for working CXX compiler: C:/Qt/2009.03/mingw/bin/g++.exe
Check for working CXX compiler: C:/Qt/2009.03/mingw/bin/g++.exe — works
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info – done
CMake Error at CMakeLists.txt:24 (qt4_wrap_cpp):
Unknown CMake command “qt4_wrap_cpp”.
Can some one let me knw how to fix this.
Managed to solve it,
1. Make sure mingw is set i the classpath
2. run the following commands to install QJson
cmake -G “MinGW Makefiles” ..
mingw32-make
mingw32-make install
Hi,
On building the project after including the qtjson header files, I get this error
undefined reference to `_imp___ZN5QJson6ParserC1Ev’
undefined reference to `_imp___ZN5QJson6ParserD1Ev
Can any one throw some light this?
I have the same error, someone to know how solve it?
Could you give me more details?
What operative system, version of Qt and cmake are you using?
What version of qjson are you trying to build?
Hello I need help, I have problem with qjson
I have same error that Deepak.
I use windows, Qt 4.6.0.
The version of qjson is qjson-0.7.1.
This is because you have to integrate the qjson0.dll in your .pro-File
e.g.
“LIBS += -L../lib -lqjson0″
if you have a fileconstellation like
c:/myproject/helloqjason.pro
c:/lib/qjson0.dll
maybe you also need
“DEFINES += QMAKE_BUILD”
to get the qjson0.dll file i had to build the qjson.pro which comes with a new package in the gitorious-repository.
—————————-
(I recogniced this solution when i looked at the example in tests/parser/parser.pro)
Hi,
how to parse the following json output through QJson ?
[{"id":2,"name":"AAA"},{"id":1,"name":"BBB"}].
Please help me. Thanks in advance
Just use this code:
You can find more details here.
I am using the following code,
QJson::Parser parser;
bool ok;
QVariantMap result = parser.parse (cityReply->readAll(), &ok).toMap();
if (!ok) {
qFatal(“An error occurred during parsing”);
exit (1);
}
qDebug() << "Name :" <readAll() in messagebox then I can view the webservice result (json String).
Please help me. Thanks in advance
I am using the following code,
QJson::Parser parser;
bool ok;
QVariantMap result = parser.parse (cityReply->readAll(), &ok).toMap();
if (!ok) {
qFatal(“An error occurred during parsing”);
exit (1);
}
qDebug() << "Name :" <readAll() in messagebox then I can view the webservice result (json String).
Have you checked parser.errorString() and parser.errorLine() output? Are you sure you are parsing some valid json object? Could you provide me the json object you are converting?
Please contact me using my email address, it will be easier.
ok i will send a mail to you.
Thank u very much. It is very nice.
Hi. im encountering error when calling parse() with non JSON object. It was actually the firstline of xml header .
is there any API to check if a string is not JSON string?
No, there isn’t such an API.
and what i mean by error is somekind of exception in VS2008.
Could you provide more details about this bug? Please use the bug tracking system on sourceforge.
How do you parse this without using too many foreach loop in a foreach loop?
{
“encoding” : “UTF-8″,
“location” : [ [ x, y, z ], [ x, y, z ], [x, y, z ] ],
“indent” : { “length” : 3, “use_space” : true }
}