2

I know that C/C++ style commenting (// ..., /* ... */) in JSON is invalid but because people with something called sense (don't know what that is) intentionally made ways to use invalid JSON e.g JSON minify or RapidJSON.

Because Qt comes with it's own JSON classes i was (not) surprised to find nothing about commenting. So the question is...

Sample input file:

test.json:

{
    // This is a comment
    /* This is a another comment */
    "property1": "It's just json",
    "foo": "bar"
}

Does Qt provide some way to use (invalid) commented JSON or do i have to use another library for that?

goulashsoup
  • 2,639
  • 2
  • 34
  • 60
  • What do you call comments ?, the json standard only serves to package information – eyllanesc Aug 25 '18 at 17:05
  • @eyllanesc I clarified! – goulashsoup Aug 25 '18 at 17:08
  • 2
    Qt does not offer such functionality, so you will have to parse before you and eliminate them. :) – eyllanesc Aug 25 '18 at 17:11
  • 1
    Are you sure that you are parsing JSON and a blob of Javascript code with an object declaration and comments ? If it is the latter, I could probably show you how to convert using Qt's JSEngine to do a JSON.stringify and extract the value out. In any case, could you post a sample input file that you are dealing with? – selbie Aug 25 '18 at 17:21
  • @selbie No i really was talking about parsing a json file. – goulashsoup Aug 25 '18 at 17:24
  • You should post a sample input file anyway. – selbie Aug 25 '18 at 18:50
  • @selbie I added one. – goulashsoup Aug 25 '18 at 21:42
  • If you really want to extend JSON to support some sort of comments and still use standard JSON parsers to deserialize them then the standard way to achieve that is to develop a filter to preprocess the extended JSON document to strip out your comments, thus converting your custom data format back to JSON. – RAM Aug 27 '18 at 08:02
  • Run the commented json through a pre-processor before reading. – Martin York Aug 29 '18 at 00:05
  • Or use an input format the supports comments. Yaml **can** look identical to Json and supports comments. – Martin York Aug 29 '18 at 00:06

1 Answers1

2

As I alluded to in the comments above, you can use the QJSEngine to do most of the heavy lifting for you. The string you have provided as an example won't evaluate as JSON per se, but it absolutely is valid JavaScript. So if we can get a JavaScript engine to evaluate that text (therefore ignoring the comments), we can use the built-in JSON object in the script engine to do all the work of converting it back to a string.

The simplest thing to do is just to utilize the JSEngine to be your JSON parser:

QString str = <your json input file that has comments>
QJSValue val = jsengine.evaluate(text);

The result of that expression is an instance of QJSValue (val), which will be the fully parsed object tree. You can use all the methods on QJSValue to enumerate the child objects and values. And you are done.

If you really want to strip the comments off for use with a different JSON parser (including the one built into Qt), you can invoke JSON.stringify on it:

#include <QJSEngine>
#include <QJSValue>

QString stripCommentsOffJSon(const QString& originalText)
{
    QJSEngine jsengine;
    QString result;

    // create an assignment statement so that evaulation works reliably
    QString evalExpression = "x=" + originalText + ";";
    QJSValue val = jsengine.evaluate(QString(evalExpression));

    if (val.isObject() || val.isArray() || val.isNumber() || val.isBool() || val.isNull() || val.isString())
    {
        QJSValue func = jsengine.evaluate(QString("JSON.stringify"));
        QJSValueList funcArgs;
        funcArgs.append(val);
        QJSValue val2 = func.call(funcArgs);
        if (val2.isString())
        {
            result = val2.toString();
        }
    }

    return result;
}

The end result is that the return value of the above function is a valid JSON string without comments. You can now feed that into any JSON parser of your choice.

Example (using your sample file)

 const char* text = "\
 {\n\
     // This is a comment\n\
     /* This is a another comment */\n\
     \"property1\": \"It's just json\",\n\
     \"foo\": \"bar\"\n\
 }";

QString result = stripCommentsOffJSon(QString(text));
std::wcout << L"Result: " << result.toStdWString() << std::endl;

Outputs:

Result: {"foo":"bar","property1":"It's just json"}

If you are already a QML app, you're good to go. For a console or widgets app, you'll need to pull in the QML library. I added this to my .pro file for a console app:

QT += qml
selbie
  • 100,020
  • 15
  • 103
  • 173