如何在Qt5中创建/读取/写入JSON文件

74

Qt5拥有一个新的JSON解析器,我想要使用它。问题在于,它的函数在通俗易懂方面并不是很清晰,而且我也可能读错了。

我想知道在Qt5中创建JSON文件的代码,以及“封装”这个词的含义。


http://qjson.sourceforge.net/ - Min Lin
Min Lin:QJson在Qt5中有点过时(甚至不确定是否已经移植),因为它带有自己的Json实现。Jim Kieger:你尝试了什么? - Frank Osterfeld
这个参考页面(https://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html)包含了QJsonDocument::QJsonDocument()和QJsonDocument::QJsonDocument(const QJsonDocument & other)函数。我尝试使用QJsonDocument,但它似乎没有创建任何东西。 - Jim Kieger
4个回答

119

示例:从文件中读取JSON

/* test.json */
{
   "appDesc": {
      "description": "SomeDescription",
      "message": "SomeMessage"
   },
   "appName": {
      "description": "Home",
      "message": "Welcome",
      "imp":["awesome","best","good"]
   }
}


void readJson()
   {
      QString val;
      QFile file;
      file.setFileName("test.json");
      file.open(QIODevice::ReadOnly | QIODevice::Text);
      val = file.readAll();
      file.close();
      qWarning() << val;
      QJsonDocument d = QJsonDocument::fromJson(val.toUtf8());
      QJsonObject sett2 = d.object();
      QJsonValue value = sett2.value(QString("appName"));
      qWarning() << value;
      QJsonObject item = value.toObject();
      qWarning() << tr("QJsonObject of description: ") << item;

      /* in case of string value get value and convert into string*/
      qWarning() << tr("QJsonObject[appName] of description: ") << item["description"];
      QJsonValue subobj = item["description"];
      qWarning() << subobj.toString();

      /* in case of array get array and convert into string*/
      qWarning() << tr("QJsonObject[appName] of value: ") << item["imp"];
      QJsonArray test = item["imp"].toArray();
      qWarning() << test[1].toString();
   }

输出

QJsonValue(object, QJsonObject({"description": "Home","imp": ["awesome","best","good"],"message": "YouTube"}) ) 
"QJsonObject of description: " QJsonObject({"description": "Home","imp": ["awesome","best","good"],"message": "YouTube"}) 
"QJsonObject[appName] of description: " QJsonValue(string, "Home") 
"Home" 
"QJsonObject[appName] of value: " QJsonValue(array, QJsonArray(["awesome","best","good"]) ) 
"best" 

例子:从字符串中读取json

将json赋值给字符串,如下所示,并使用之前展示的readJson()函数:

val =   
'  {
       "appDesc": {
          "description": "SomeDescription",
          "message": "SomeMessage"
       },
       "appName": {
          "description": "Home",
          "message": "Welcome",
          "imp":["awesome","best","good"]
       }
    }';

输出

QJsonValue(object, QJsonObject({"description": "Home","imp": ["awesome","best","good"],"message": "YouTube"}) ) 
"QJsonObject of description: " QJsonObject({"description": "Home","imp": ["awesome","best","good"],"message": "YouTube"}) 
"QJsonObject[appName] of description: " QJsonValue(string, "Home") 
"Home" 
"QJsonObject[appName] of value: " QJsonValue(array, QJsonArray(["awesome","best","good"]) ) 
"best" 

我发现了一个非常好的例子,它是希望之星,我已经完全按照这个例子进行了操作。然而,当我调试这个例子时,条目的值显示为空。这是在QT中创建、读取和写入JSON文件的唯一“逐步”示例吗?我无法弄清楚我可能做错了什么。使用QT Creator 3.0.1。谢谢。 - Shawn
1
@Shawn 在QT Creator的帮助选项卡中搜索JSON Save Game Example。这个示例基本上演示了读写JSON值(包括数组)所需做的一切。JSON Save Game Example - Vikas Bhargava
如果您使用QByteArray,则可以跳过将utf-8字节转换为utf-16然后再转回去(QString,toUtf8())。 - jfs
将整个文件加载到字符串中,然后解析字符串,真的吗? - Youda008
在我检查了可选的错误参数之前,我一直遇到麻烦:QJsonParseError err; QByteArray utf8String = jsonString.toUtf8(); QJsonDocument d = QJsonDocument::fromJson(utf8String, &err); - Pescolly
显示剩余2条评论

4

在QT下使用JSON实际上非常愉快 - 令我惊讶。这是创建带有一些结构的JSON输出的示例。

请原谅我没有解释所有字段的含义 - 这是一个无线电处理输出脚本。

这是QT C ++代码

void CabrilloReader::JsonOutputMapper()
{
  QFile file(QDir::homePath() + "/1.json");
  if(!file.open(QIODevice::ReadWrite)) {
      qDebug() << "File open error";
    } else {
      qDebug() <<"JSONTest2 File open!";
    }

  // Clear the original content in the file
  file.resize(0);

  // Add a value using QJsonArray and write to the file
  QJsonArray jsonArray;

  for(int i = 0; i < 10; i++) {
      QJsonObject jsonObject;
      CabrilloRecord *rec= QSOs.at(i);
      jsonObject.insert("Date", rec->getWhen().toString());
      jsonObject.insert("Band", rec->getBand().toStr());
      QJsonObject jsonSenderLatObject;
      jsonSenderLatObject.insert("Lat",rec->getSender()->fLat);
      jsonSenderLatObject.insert("Lon",rec->getSender()->fLon);
      jsonSenderLatObject.insert("Sender",rec->getSender_call());
      QJsonObject jsonReceiverLatObject;
      jsonReceiverLatObject.insert("Lat",rec->getReceiver()->fLat);
      jsonReceiverLatObject.insert("Lon",rec->getReceiver()->fLon);
      jsonReceiverLatObject.insert("Receiver",rec->getReceiver_call());
      jsonObject.insert("Receiver",jsonReceiverLatObject);
      jsonObject.insert("Sender",jsonSenderLatObject);
      jsonArray.append(jsonObject);
      QThread::sleep(2);
    }

  QJsonObject jsonObject;
  jsonObject.insert("number", jsonArray.size());
  jsonArray.append(jsonObject);

  QJsonDocument jsonDoc;
  jsonDoc.setArray(jsonArray);
  file.write(jsonDoc.toJson());
  file.close();
  qDebug() << "Write to file";
}

它需要一个内部QT结构(指向CabrilloRecord对象的指针列表,您可以忽略它),并提取一些字段。然后以嵌套的JSON格式输出这些字段,该格式如下所示。
[
    {
        "Band": "20",
        "Date": "Sat Jul 10 12:00:00 2021",
        "Receiver": {
            "Lat": 36.400001525878906,
            "Lon": 138.3800048828125,
            "Receiver": "8N3HQ       "
        },
        "Sender": {
            "Lat": 13,
            "Lon": 122,
            "Sender": "DX0HQ       "
        }
    },
    {
        "Band": "20",
        "Date": "Sat Jul 10 12:01:00 2021",
        "Receiver": {
            "Lat": 36.400001525878906,
            "Lon": 138.3800048828125,
            "Receiver": "JA1CJP      "
        },
        "Sender": {
            "Lat": 13,
            "Lon": 122,
            "Sender": "DX0HQ       "
        }
    }]

我希望这篇文章能够加速其他人在这个主题上的进展。

2
不幸的是,许多 JSON C++ 库的 API 使用起来并不简单,而 JSON 的初衷是易于使用的。
因此,我尝试使用 jsoncpp,它来自于gSOAP 工具,用于处理上面某个答案中展示的 JSON 文档。下面是使用 jsoncpp 生成的 C++ 代码,用于构造一个 JSON 对象,然后将其以 JSON 格式写入 std::cout:
value x(ctx);
x["appDesc"]["description"] = "SomeDescription";
x["appDesc"]["message"] = "SomeMessage";
x["appName"]["description"] = "Home";
x["appName"]["message"] = "Welcome";
x["appName"]["imp"][0] = "awesome";
x["appName"]["imp"][1] = "best";
x["appName"]["imp"][2] = "good";
std::cout << x << std::endl;

这是由jsoncpp生成的代码,用于解析从std :: cin中提取JSON的值(根据需要替换USE_VAL):
value x(ctx);
std::cin >> x;
if (x.soap->error)
  exit(EXIT_FAILURE); // error parsing JSON
#define USE_VAL(path, val) std::cout << path << " = " << val << std::endl
if (x.has("appDesc"))
{
  if (x["appDesc"].has("description"))
    USE_VAL("$.appDesc.description", x["appDesc"]["description"]);
  if (x["appDesc"].has("message"))
    USE_VAL("$.appDesc.message", x["appDesc"]["message"]);
}
if (x.has("appName"))
{
  if (x["appName"].has("description"))
    USE_VAL("$.appName.description", x["appName"]["description"]);
  if (x["appName"].has("message"))
    USE_VAL("$.appName.message", x["appName"]["message"]);
  if (x["appName"].has("imp"))
  {
    for (int i2 = 0; i2 < x["appName"]["imp"].size(); i2++)
      USE_VAL("$.appName.imp[]", x["appName"]["imp"][i2]);
  }
}

这段代码使用了gSOAP 2.8.28的JSON C++ API。我并不期望人们更改库,但我认为这个比较有助于对比JSON C++库。

1

一个使用例子将会很好。在Qt论坛上有一些例子,但您是正确的,官方文档应该加以扩展。

QJsonDocument 单独并不会产生任何内容,您需要向其中添加数据。这可以通过 QJsonObjectQJsonArrayQJsonValue 类来完成。顶层项必须是数组或对象(因为 1 不是有效的 json 文档,而 {foo: 1} 是有效的)。


1
经过研究,我想我会继续使用QSettings而不是使用JSon来处理某些事情。谢谢你的帮助。 - Jim Kieger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接