Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    QScriptEngine, converting JSON data to QVariants

    General and Desktop
    3
    6
    9379
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • G
      gallafent last edited by

      Hi All,

      I'm attempting to read some objects from pre-existing JSON data. I'm running in to trouble when the data is non-trivial. The actual data I need to read is a lot more complex than the samples below, but they demonstrate the problem! I expect this is due to my misreading of the documentation (or misunderstanding of the concepts!) but anyway …

      According to http://doc.qt.nokia.com/4.7/qscriptvalue.html#toVariant , "The array is converted to a QVariantList. Each element is converted to a QVariant, recursively; cyclic references are not followed." - so why when I try to read a simple 2-element array (which I expect to come out as a list) is each element of the QVariantList not the appropriate type of qvariant (string), but instead a "usertype" variant, seemingly with no content?

      With the single string, the output from the code fragment below is:

      valid
      type: QVariant::QString
      "a"

      With the other example data (commented out below), though, an array of two strings, the output is:

      list
      type: QVariant::UserType
      ""
      type: QVariant::UserType
      ""

      (apologies, not quite a complete ready-to-compile sample, lifted from a larger project, but almost complete, just needs the right #includes I think!)

      @void debugPrintVariant (QVariant const & v)
      {
      if (! v. isValid ()) {
      qDebug () << "invalid";
      }
      if (QVariant:: List == v. type ()) {
      qDebug () << "list";
      for (QList <QVariant>:: const_iterator i = v.toList (). begin (); i != v. toList (). end (); ++ i)
      debugPrintVariant (*i);
      } else if (QVariant:: Map == v. type ()) {
      qDebug () << "map";
      for (QMap <QString, QVariant>:: const_iterator i = v. toMap (). begin (); i != v. toMap (). end (); ++ i) {
      qDebug () << "Key: " << i. key ();
      debugPrintVariant (i. value ());
      }
      } else {
      qDebug () << "type: " << v. type ();
      qDebug () << v. toString ();
      }
      }

      void main () {

      // This one works OK
      QString jsonScript = "{"items": "a"}";
      // This one, each list element is "user type", instead of string - how do I get at the data?
      //QString jsonScript = "{"items": ["a", "b"]}";

      QScriptEngine se;
      QScriptValue sv = se.evaluate ("JSON.parse").call(QScriptValue(), QScriptValueList() << jsonScript);
      // Alternative parsing method, same result
      //QScriptValue sv = se. evaluate ("(" + jsonScript + ")");

      QVariant rootVariant = sv. property("items"). toVariant ();

      debugPrintVariant (rootVariant);
      }@

      1 Reply Last reply Reply Quote 0
      • B
        baysmith last edited by

        You're iterating over the values wrong. The QVariant::toList() and QVariant::toMap() functions return a new list or map with each call. You can't compare iterators from the first call of toList() with iterators from the second call of toList(). Change it to

        @
        QList<QVariant> list = v.toList();
        for (QList<QVariant>::const_iterator i = list.begin(); i != list.end(); ++i)
        debugPrintVariant(*i);
        @

        or better, use foreach
        @
        foreach (QVariant const &i, v.toList())
        debugPrintVariant(i);
        @

        Nokia Certified Qt Specialist.

        1 Reply Last reply Reply Quote 0
        • A
          andre last edited by

          Note that if you just want to parse JSON, you can do so without using QtScript. Take a look at QJSON, for instance.

          1 Reply Last reply Reply Quote 0
          • G
            gallafent last edited by

            Thanks for quick and accurate response Bradley, I completely missed that, forgot I was actually transforming the data not just taking a view of it. D'oh.

            Using JSON.parse in this way now works well. Are there any performance or other considerations that mean I should prefer the "JSON.parse" or "QScriptEngine.evaluate" approach?

            1 Reply Last reply Reply Quote 0
            • A
              andre last edited by

              [quote author="gallafent" date="1300181725"]Using JSON.parse in this way now works well. Are there any performance or other considerations that mean I should prefer the "JSON.parse" or "QScriptEngine.evaluate" approach?[/quote]
              I seem to remember that the latter is unsafe. It might execute anything, while JSON.parse should be safe. You should not trust the data you get from outside, so just executing it is probably a bad idea. You should check this though, as this is from a vague memory on the topic.

              1 Reply Last reply Reply Quote 0
              • G
                gallafent last edited by

                Good point Andre, thanks.

                Much of the data is packaged with the app, and so "safe", but some will indeed come down the wire, so your point about the extra safety provided by using the JSON.parse approach is certainly applicable!

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post