[Solved] Parsing a JSon reply issue



  • 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 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?

    Thank you!



  • You don't "have to use" Qt script. There are plenty of other parsers out there. "This one":https://github.com/nlohmann/json for instance. Or "this":http://libqxt.bitbucket.org/doc/tip/qxtjson.html one if you want to stay closer to Qt.



  • Hi Andre,

    What I don't understand is why I was able to get a part but not all I need... I mean, I was following this example: "Example":http://www.makina-corpus.org/blog/access-json-webservice-qt-c

    So the logical thing is that if I got the right-side part of "data", I had to be able to get the next info, right? :P

    Btw...Thank you, I'll take a look with the second one (dunno how to include the first one on my project still). One quick question about the second one:

    To use that library I understand that you have to include the Qxt module to the pro:

    CONFIG += qxt
    QXT = core

    and then: #include <Qxt> But seems tahtmy project still doesnt have the Qxt library (I've run qmake and build it again)



  • You can usually just pick up single classes too. AFAIK, the project as such is no longer maintained, and the recommended use is now to use classes directly.



  • So I add json.cc and json.h from the first link to my project...

    I got some errors that I solved but now it says:

    error: 'using object_t = class std::map<std::basic_string<char>, nlohmann::json>' has no member named 'emplace'

    In a line in middle of the *.cc.... Isn't there any other way????
    Hate when things aren't easy -.-" hehe



  • Sounds like you are not using C++/11, which is needed for this code to work.



  • Yes, that was the first error i solved. I put it on the .pro file as

    QMAKE_CXXFLAGS += -std=c++11
    and tried too with
    QMAKE_CXXFLAGS += -std=gnu++11

    And the compile output gaves something like:

    @
    g++ -c -pipe -std=c++11 -g -Wall -W -D_REENTRANT -DQT_SCRIPT_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/lib/qt4/mkspecs/linux-g++[...]@



  • Did you try with simply putting
    @
    CONFIG += c++11
    @
    in your .pro file?



  • Then I get the same error I had first:

    /usr/lib/gcc/i686-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support is currently experimental, and must be enabled with the -std=c++11 or -std=gnu++11 compiler options.

    Which I solved with
    @
    QMAKE_CXXFLAGS = -std=c++11

    (and even with the next line instead of the other the error dissapears)
    QMAKE_CXXFLAGS = -std=gnu+11
    @

    The error I was saying is in line 197:
    @
    for (auto& element : a)
    {
    value_.object->emplace(std::make_pair(std::move(element[0]), std::move(element[1]))); // HERE IS THE ERROR
    }
    @



  • I've found this other solution: "JSon":https://github.com/gaudecker/qt-json

    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 are empy. Any Idea of how to make that work?

    Thanks!


  • Moderators

    Hi,

    [quote author="roseicollis" date="1423496917"]But try1 and try2 are empy. Any Idea of how to make that work?[/quote]Your data is a JSON array, not a JSON object.



  • Oh I see...

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

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

    I don't really know how to parse that array... I've tried this too:

    @
    QtJson::JsonObject bbb = QtJson::parse(result["data"].toString(), ok).toMap();
    qDebug() << bbb;
    @
    But it only prints: QMap()

    So... I'm really stuck there... -.-''


  • Moderators

    Are you familiar with JSON syntax?

    • [ ] represents an array.
    • { } represents an object.

    You need to understand your structure first: You have 1 array. That array contains 2 objects. Each object contains 2 strings

    Extract the objects from the array like this:
    @
    auto object1 = result[0];
    auto object2 = result[1];
    @

    After that, you can extract the "Name" and "data" fields from the objects.

    Remember, arrays are indexed by integers, while objects/maps are indexed by strings.



  • Hi JKSH,

    Ermmm noup, I wasn't familiar with it but now I understand it better :) Thanks!

    One thing: what is auto for you? O.o a JsonObject?

    @
    QtJson::JsonObject object1 = result[0].toMap(); //object1 returns: QMap()
    QVariant object1 = result[0]; //object1 returns: QVariant(, )
    QVariant object1 = result[0].toString();//object1 returns: QVariant(QString, )
    @

    EDIT: Didn't know there were something called 'auto' O.o but trying that:

    @
    QtJson::JsonObject result = QtJson::parse(myJson, ok).toMap();
    auto object1 = result[0];
    QtJson::JsonObject trying = QtJson::parse(object1, ok).toMap();
    qDebug() <<" trying msg" << trying;
    @

    it says: error: no matching function for call to 'parse(QVariant&, bool&)'
    And if I try with
    @
    QtJson::JsonObject trying = QtJson::parse(object1["Name"], ok).toMap();
    @
    It says: error: no match for 'operator[]' in 'object1["Name"]'


  • Moderators

    You're welcome. :)

    [quote author="roseicollis" date="1423567075"]
    @
    QtJson::JsonObject result = QtJson::parse(myJson, ok).toMap();
    @
    [/quote]2 issues:

    Like I said before, your data is an array, not an object. So, you should make result a JsonArray, not a JsonObject. Also, toMap() produces an object. You want to use toList() instead, which produces an array.

    What type is myJson? Your compiler complained because you passed a QVariant into QtJson::parse(). What type does it actually accept? (hint: look inside json.h)

    [quote author="roseicollis" date="1423567075"]EDIT: Didn't know there were something called 'auto' O.o[/quote]'auto' is a "C++11 keyword":http://geekswithblogs.net/BlackRabbitCoder/archive/2012/03/15/c-little-wonders-the-c11-auto-keyword-redux.aspx. When you use it, the compiler will try to figure out the variable's type automatically.



  • Hi again ^^

    [quote author="JKSH" date="1423568300"]
    Like I said before, your data is an array, not an object. So, you should make result a JsonArray, not a JsonObject. Also, toMap() produces an object. You want to use toList() instead, which produces an array.
    [/quote]
    Didn't know that it creates an object too... (anyway i tried before with strings and bytearray hopeing something works hahaha but not obviously)

    [quote author="JKSH" date="1423568300"]
    What type is myJson? Your compiler complained because you passed a QVariant into QtJson::parse(). What type does it actually accept? (hint: look inside json.h)
    [/quote]

    myJson is a QString:
    @
    QNetworkRequest request(_Url);
    QNetworkReply *reply = nam->get(request);
    QString myJson = (QString)reply->readAll();
    @

    I know that this error is because of the types but I was thinking that it takes Variants and now saw that not. The definition of parse is:
    @
    QVariant parse(const QString &json, bool &success);
    @

    If I try with:
    @
    QtJson::JsonArray result = QtJson::parse(myJson, ok).toList();
    qDebug() << " a " << result;
    auto object1 = result[0];
    qDebug() << " a1 " << object1;
    @

    Then it prints:
    a()
    ASSERT failure in QList<T>::operator[]: "index out of range",

    Which is normal if a() is empty O.o

    I'll have to inquire about what c++11 is, really thank you so much! Now I have new weekend reading :D


  • Moderators

    Hmm... what do you get if you do this?

    @
    qDebug() << myJson;
    qDebug() << QtJson::parse(myJson, ok);
    qDebug() << ok;
    @

    C++11 is the updated version of C++ which came out in 2011 :) It offers lots of new language features to make C++ more powerful and easier to use. C++14 is in the works, but it's no longer 2014 now so the update will probably be called C++15 instead.



  • This returns the next:

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

    QVariant(QVariantMap, QMap(("data", QVariant(QString, "[{"Name":"One","Code":""},{"Name":"Two","Code":"Alpha"}]") ) ) )

    true
    @

    wooow I thought there were only C, C# and C++ .... what an inonce girl I am XDDDD I will definitely look more about it at the weekend, it sounds really interesting!


  • Moderators

    [quote author="roseicollis" date="1423572240"]
    @
    "{"data":"[{"Name":"One","Code":""},{"Name":"Two","Code":"Alpha"}]"}"
    @

    [/quote]I'm so sorry... I though myJson was
    @
    [{"Name":"One","Code":""},{"Name":"Two","Code":"Alpha"}]
    @

    ...that's why I thought your data was an array of 2 objects. :( Sorry for sending you on a wild goose chase!

    Anyway, your actual JSON data is: 1 object which contains 1 string value. I must say your data is formatted quite strangely (where did you get it from?).

    So, in the first run, you can only extract one string:
    @
    QtJson::JsonObject outerObject = QtJson::parse(myJson, ok).toMap();
    QString innerString = outerObject.toString();

    qDebug() << myJson;
    qDebug() << innerString;
    @

    You will see that myJson contains lots of '' characters, but innerString doesn't. That's because the data in outerObject is escaped -- the JSON parser treats it as a single string instead of a JSON array.

    Anyway, after parsing it the first time, you now have un-escaped data in innerString, so you can send it through the JSON parser again to extract the array:

    @
    QtJson::JsonArray outerArray = QtJson::parse(innerString, ok).toList();

    qDebug() << ok;
    qDebug() << outerArray;
    @

    Now, you can apply my previous posts.

    Good luck!

    [quote author="roseicollis" date="1423572240"]wooow I thought there were only C, C# and C++ .... what an inonce girl I am XDDDD I will definitely look more about it at the weekend, it sounds really interesting![/quote]There are lots and lots of programming languages out there. :) C, C# and C++ are different languages.

    However, C++03, C++11, and C++14 are different versions of the same language.

    Happy reading!



  • [quote author="JKSH" date="1423574139"]
    . :( Sorry for sending you on a wild goose chase!
    [/quote]
    No problem! I learnt a lot with that too :D

    [quote author="JKSH" date="1423574139"]
    I must say your data is formatted quite strangely (where did you get it from?)
    [/quote]

    I don't know which should be its structure but this is what I will receive from a webservice which is made by a work mate and the only thing I know is: I have to parse it and show it on a widget (Still dunno if combobox or what will be the best option)

    [quote author="JKSH" date="1423574139"]
    @
    QtJson::JsonObject outerObject = QtJson::parse(myJson, ok).toMap();
    QString innerString = outerObject.toString();

    qDebug() << myJson;
    qDebug() << innerString;
    @
    [/quote]

    I had to make some changes to make it work:

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

    So:

    • DD returns: DD QVariant(QString, "One")

    Now I'm trying to get that "One" string alone but at least I can see it!! I'm almost there, so cloose!

    [quote author="JKSH" date="1423574139"]
    There are lots and lots of programming languages out there. :) C, C# and C++ are different languages.
    However, C++03, C++11, and C++14 are different versions of the same language.
    [/quote]

    Yes, I know there are soo many programming languages but didn't think about versions.. Never though they exist for the languages too haha


  • Moderators

    [quote author="roseicollis" date="1423581028"]I had to make some changes to make it work:[/quote]Good catch!

    [quote author="roseicollis" date="1423581028"]So:

    • DD returns: DD QVariant(QString, "One")

    Now I'm trying to get that "One" string alone but at least I can see it!! I'm almost there, so cloose![/quote]Yep, almost there! :) object1["Name"] is a QVariant, so see http://doc.qt.io/qt-5/qvariant.html for clues

    [quote author="JKSH" date="1423574139"]Yes, I know there are soo many programming languages but didn't think about versions.. Never though they exist for the languages too haha[/quote]I think Shakespeare's English and modern English are 2 different versions of English ;-P



  • [quote author="JKSH" date="1423582568"]
    Yep, almost there! :) object1[“Name”] is a QVariant, so see http://doc.qt.io/qt-5/qvariant.html for clues
    [/quote]
    Yesterday I was trying with object1["Name"].toString() but it was saying all time that there were no func like toString()... today I tried it again because it sounds logical for me and now it works... -. -'' I really hate programing when that happens hahahaha... anyway, it works :D So I'm happy :D

    [quote author="JKSH" date="1423582568"]
    I think Shakespeare’s English and modern English are 2 different versions of English ;-P
    [/quote]
    Wooow, do you really think that?? O.o I thought that the english nowadays was the same as shakespears or as the cavemen.. :P I was just joking ^.^ Haha that is a really really nice example!

    Thank you for all your help guys! And special thanks for you JKSH. I have enjoyed so much this problem and learnt a lot! :D


  • Moderators

    You're most welcome :)

    Happy coding!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.