PDA

View Full Version : Parsing a JSon webservice reply issue



roseicollis
6th February 2015, 13:05
Hi,

I’m doing a request to an url which gives me the next Json reply:


"{"data":"[{\"Name\":\"One\",\"Code\":\"\"},{\"Name\":\"Two\",\"Code\":\"Alpha\"}]"}"
I am using Qt 8.4.5 so I have to do it with QNetwork and QScript. So following an example I saw (Example (http://www.makina-corpus.org/blog/access-json-webservice-qt-c))I did the next:


QNetworkRequest request(_Url);
QNetworkReply *reply = nam->get(request);

QString InfoByteArray = (QString)reply->readAll();

if ( reply->error()== QNetworkReply::NoError)
{
//------------ JSON Parser --------------//

QScriptEngine engine;
QScriptValue result = engine.evaluate("("+InfoByteArray+")");

QScriptValue InfoData= result.property("data");
qDebug() << "InfoData" << InfoData.toString();
}

With that I get all the part on the right of “data”:


[{"Name":"One","Code":""},{"Name":"Two","Code":"Alpha"}]"
Now I want to take the Name en Code values ofc but I can’t get them, I try doing this but never goes into the while:


QScriptValueIterator it(InfoData);
while (it.hasNext())
{
it.next();
QScriptValue entry = it.value();

QString name= entry.property("Name").toString(); //this doesnt works
QString name2= entry.property("data").property("Name").toString(); //this either
}
And if I try doing that out of the while, I just get empty strings :

QString name= result.property("Name").toString(); // qDebug() << name; returns ""
QString name2= entry.property("data").property("Name").toString();
So…Any Idea of what am I doing wrong here so I can't get the Name or the Code values??

Thank you!

ChrisW67
6th February 2015, 21:08
The JSON data you present is a single object with one key "data" and a string value. That outer object does not contain any other key/value pairs or subordiante object structures.

If you want to parse the "data" string as JSON then you will need to pass that value through the QScriptEngine (Or QJson) to get an array of objects each with Name and Code keys.

roseicollis
9th February 2015, 08:07
Hi ChrisW67,

Thanks for your reply.

If you want to parse the "data" string as JSON
Well in fact what I need is the information. I don't care about if its a Json or not.


pass that value through the QScriptEngine (Or QJson)
JSon is not possible because its for Qt5+ and I'm working on Qt4.8.5 (I just noticed I put it wrong upside.. of course its not 8.4.5 XD)
So it has to be through QScriptEngine but I tried so many different ways and I couldn't get it, could you gave me an example please?

Thanks!

wysota
9th February 2015, 08:16
QJson is an external library for Qt4 for parsing JSON data. Regarding QScriptEngine, Chris already told you what to do - pass the string representing the value through the parser again. To be honest it is kind of weird that the service stringifies the value instead of passing it directly in the JSON document.

roseicollis
9th February 2015, 16:03
Oh! Sorry I didn't understand it well then.. I didn't know there were external librarys for that( that is kinda new for me sorry).

It seems that it works but now I can't get the name and code values, I'm trying to do:



bool ok;

QtJson::JsonObject result = QtJson::parse(myJson, ok).toMap();
if(!ok) {
qFatal("An error occurred during parsing");
}else
{
qDebug() << "data" << result["data"].toString();
qDebug() << " try1" << result["Name"].toString();

QtJson::JsonObject nested = result["data"].toMap();
qDebug() << "try2:" << nested["Name"].toString();



But try1 and try2 qDebug() are empy.

Thank you!

ChrisW67
9th February 2015, 20:27
Try1 is empty for the same reason as your original post. There is no "Name" key in the outer JSON object.

Try2 is empty because you have not run the result["data"] string through the QtJson::parse() function to get at the object it encodes.

Your input data is this:


{
"data": "[{\"Name\":\"One\",\"Code\":\"\"},{\"Name\":\"Two\",\"Code\":\"Alpha\"}]"
}

That is, your "data" string is a JSON encoded message (string) inside another JSON object.
And your code is expecting this:


{
"data": [
{
"Name": "One",
"Code": ""
},
{
"Name": "Two",
"Code": "Alpha"
}
]
}
. Which is, as wysota pointed out, what you would more typically expect. The situation is odd but not unworkable.

roseicollis
10th February 2015, 10:44
Oh I see...I've tried this :



QtJson::JsonObject result = QtJson::parse(myJson, ok).toMap();
QtJson::JsonObject bbb = QtJson::parse(result["data"].toString(), ok).toMap();
qDebug() << bbb;

But it only prints: QMap()

And I've tried too:


QtJson::JsonArray nested = result["data"].toMap();
qDebug() << "try2:" << nested["Name"].toString();

Which says:


conversion from 'QMap<QString, QVariant>' to non-scalar type 'QtJson::JsonArray {aka QList<QVariant>}' requested


I'm really stuck there, trying to parse this simple JSon... -.-'' Could you please put a code-example or explain it in other way? I have a really mess on my head right now trying to understand all this with Qmaps, QVariants and lists...I'm using this library: JSon (https://github.com/gaudecker/qt-json)

Thank you and sorry for the problems.

wysota
10th February 2015, 12:56
Your data value is an array, not a map. It is an array containing two maps (objects) to be exact.

roseicollis
10th February 2015, 15:21
Finally I understood it... more or less... And I have this:



QtJson::JsonObject outerObject = QtJson::parse(myJson, ok).toMap();
QString innerString = outerObject["data"].toString();
QtJson::JsonArray outerArray = QtJson::parse(innerString, ok).toList();
auto object1 = outerArray[0].toMap();
qDebug() << " DD" << object1["Name"];


which output is: DD QVariant(QString, “One”)

But I can't get only de "One" string because I don't really know what is that output... does it represent to be a list of one QVariant which have a QString or... I don't know...

wysota
10th February 2015, 16:55
Finally I understood it... more or less... And I have this:



QtJson::JsonObject outerObject = QtJson::parse(myJson, ok).toMap();
QString innerString = outerObject["data"].toString();
QtJson::JsonArray outerArray = QtJson::parse(innerString, ok).toList();
auto object1 = outerArray[0].toMap();
qDebug() << " DD" << object1["Name"];


which output is: DD QVariant(QString, “One”)

But I can't get only de "One" string because I don't really know what is that output... does it represent to be a list of one QVariant which have a QString or... I don't know...

I have no idea what you mean. Have a look at QVariant api how to determine if the variant is a string, int, llis or map.

ChrisW67
10th February 2015, 20:26
The value object1["Name"] is returned as a QVariant and needs to be converted to a base type using toString(), toInt() etc. it has to be done this way because the Javascript value can be anything including another array or object.

roseicollis
11th February 2015, 08:32
The value object1["Name"] is returned as a QVariant and needs to be converted to a base type using toString(), toInt() etc. it has to be done this way because the Javascript value can be anything including another array or object.

This is what I thought but I can't put anything after ] and if i force it with object1["Name"].toString it says that there is nothing like toString()...

Edit: Now it works dunno why so... problem solved.

Thank you for all guys!

wysota
11th February 2015, 08:42
After ] try putting a dot (.) followed by "type()" and see what that method returns.