Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-138581

QJsonValue doesn't represent JSON numbers properly

XMLWordPrintable

    • Icon: Suggestion Suggestion
    • Resolution: Invalid
    • Icon: P3: Somewhat important P3: Somewhat important
    • None
    • 6.8.3
    • None

      RFC8259 section 6 (https://datatracker.ietf.org/doc/html/rfc8259#section-6) states that numbers in JSON consist of "an integer component that may be prefixed with an optional minus sign, which may be followed by a fraction part and/or an exponent part."

      This means that given the following input:

      { "someInt": 5, "someDouble": 5.0, "otherDouble": 5.1 }" 

      a conforming parser should ensure that the "someInt" value only consists of an integer component, whereas the "someDouble" and "otherDouble" values have both an integer component plus a fractional component.

       

      QJsonValue does not differentiate between the "someInt" and "someDouble" case properly - QJsonValue::isDouble() returns true for both values, but calling QJsonValue::toVariant() returns `QVariant(qlonglong, 5)` for both, even though QJsonValue::toVariant() correctly returns `QVariant(double, 5.1)` for the "otherDouble".

       

      Clearly, QJsonValue::isDouble() should return false for "someInt", and true for "someDouble", and QJsonValue::toVariant() should return `QVariant(double, 5.0)` for "someDouble".

       

      Repro:

      #include <QCoreApplication>
      #include <QJsonDocument>
      #include <QJsonObject>
      #include <QJsonValue>
      #include <QVariant>
      #include <QString>
      #include <QtDebug>
      
      int main(int argc, char *argv[])
      {
          QCoreApplication app(argc, argv);
          QJsonDocument doc = QJsonDocument::fromJson(
              QByteArrayLiteral("{ \"someInt\": 5, \"someDouble\": 5.0, \"otherDouble\": 5.1 }"));
      
          QJsonObject obj = doc.object();
          QJsonValue i = obj.value("someInt");
          QJsonValue d = obj.value("someDouble");
          QJsonValue f = obj.value("otherDouble");
      
          qWarning() << "parse output:\n"
              << "i.type = " << i.type() << ","
              << "i.isDouble = " << i.isDouble() << ","
              << "i.toString = " << i.toString() << ","
              << "i.toVariant = " << i.toVariant() << ";\n"
              << "d.type = " << d.type() << ","
              << "d.isDouble = " << d.isDouble() << ","
              << "d.toString = " << d.toString() << ","
              << "d.toVariant = " << d.toVariant() << ";\n"
              << "f.type = " << f.type() << ","
              << "f.isDouble = " << f.isDouble() << ","
              << "f.toString = " << f.toString() << ","
              << "f.toVariant = " << f.toVariant() << ";\n";
      
          return 0;
      }

       

      Output:

      parse output:
       i.type =  2 , i.isDouble =  true , i.toString =  "" , i.toVariant = QVariant(qlonglong, 5) ;
       d.type =  2 , d.isDouble =  true , d.toString =  "" , d.toVariant = QVariant(qlonglong, 5) ;
       f.type =  2 , f.isDouble =  true , f.toString =  "" , f.toVariant = QVariant(double, 5.1) ;

       

      Expected output:

      parse output:
       i.type =  6 , i.isDouble =  false, i.toString =  "" , i.toVariant = QVariant(qlonglong, 5) ;
       d.type =  2 , d.isDouble =  true , d.toString =  "" , d.toVariant = QVariant(double, 5) ;
       f.type =  2 , f.isDouble =  true , f.toString =  "" , f.toVariant = QVariant(double, 5.1) ; 

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            thiago Thiago Macieira
            chrisadams Christopher Adams
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:

                There is 1 open Gerrit change