我需要使用JSON通过网络传输高容量数据,然后在高流量和高性能要求的情况下在运行时在Qt中解释它。基本上,需要处理数百甚至数千或更多JSON文档的任意大小和复杂性。我对如何做到这一点有点自由,但我正在仔细考虑我的选择,到目前为止,我不满足于它们似乎是什么。
主要关注的是查找和修改速度,而从/到JSON的转换在我的上下文中不太重要,因为我可以处理较慢的入口和/或输出,无论如何都是不稳定的。但是一旦数据通过,就需要随时可用。
我看到他们的选择:
1)选项1是直接使用Qt 5中的JSON支持类。但缺点是,为了在JSON数据树中的某处修改单个值,需要复制整个事物,然后再使用修改后的值再次创建JSON。对于单个修改,这可能是非常昂贵的。 QJsonValueRef在某种程度上有助于它,但不允许迭代整个结构,因为结构中的每个对象仍然需要被复制。
2)将JSON转换为QVariantMap(QMap)并使用它。除了来回转换的开销之外,它遇到与1)相同的问题,因为QAssociativeIterable不会返回对其项的引用,因此不能在不先复制每个QVariant的情况下进入结构。基本上它允许在QVariantMap的单个子级别中进行非复制迭代。它可能仍然比直接使用Qt的JSON类更好,但基本上它似乎与1)具有相同的限制。
3)将JSON转换为我自己的数据结构,该结构允许在不复制任何值的情况下通过结构和数据修改进行下降。每个"级别"将成为其父母将访问的对象,从而允许以任意深度非拷贝地访问其内容。这个解决方案会受到以下事实的影响:我很可能无法为每个"级别实现查找机制。这几乎和Qt / STL容器一样有效。但也许我可以将Qt的容器与这种方法结合起来,将子指针存储在其中尽可能快的运算符==重载...
4)将JSON转换为平面的二维数据结构,例如:
Level1/Level2/key : value
Level1/Level2/key2 : value2
Level1/key3 : value3
这种方法在数据存储方面存在大量冗余,并且与JSON的转换成本很高,但可以提供最大的查找/修改速度,因为它不需要进入任何数据结构。然而,这种好处的成本对我来说似乎太大了(冗余和慢速转换)。
我有点倾向于选项3,但也许还有其他选择。我想听听你对这个问题的想法和/或想法。或者,JSON首先不是通过网络进行数据传输的正确工具。
答案 0 :(得分:2)
如果you look at the Qt source code您将意识到Qt json对象已经过优化:
要遍历结构,请使用QJsonObject
类。
QJsonValue QJsonObject::value(const QString & key);
对象类型是最小的。但正如您所指出的,它为字符串类型创建了一个新字符串;它还对数值执行“强制转换”。请注意,在解析了进一步处理之后,只有当您开始处理QJsonValue
时,才会产生内存开销。
因此选项1并没有那么糟糕。根据你的条件,选项2很可怕。我没有看到任何优势。由于您自己指定的原因,选项4是噩梦。在取得一些进展后,你后悔的那种工作。
如果严格使用Qt json类是不够的,那么请转到更高效的库rapidjson。
优点:
不便之处
它完成了你的选择3试图做的事情。
答案 1 :(得分:1)
我实现了一个便利库,以便于JSON查找和修改。我的库不是像QJson API那样被隐式共享,而是使用显式共享实现。这使得编辑变得更容易,但却失去了安全性。看看:
https://github.com/juangburgos/QJsExplicit
您可以这样做:
QJsDocument doc;
// create test object
QJsObject testobj = doc.createObject("testobj");
testobj.setAttribute("attr1", "hola mundo");
testobj.setAttribute("attr2", 3.1416);
testobj.setAttribute("attr3", false);
// create test array
QJsArray testarr = doc.createArray("testarr");
testarr.appendValue(2);
testarr.appendValue(4);
testarr.appendValue(6);
testarr.appendValue(8);
// create test array child object
QJsObject arrchildobj = testarr.createObject("whatever");
arrchildobj.setAttribute("xxx", true);
arrchildobj.setAttribute("yyy", 8);
arrchildobj.setAttribute("zzz", 7.8);
// orphan object append to test
QJsObject orphanobj;
orphanobj.setKeyName("orphanobj");
orphanobj.setAttribute("A", 1);
orphanobj.setAttribute("B", 2);
orphanobj.setAttribute("C", 3);
testobj.appendChild(orphanobj);
// edit through shallow copy of the document
QJsDocument doc2 = orphanobj.ownerDocument();
if (doc2.getChildByKey("testarr").isArray())
{
QJsArray testarr2 = doc2.getChildByKey("testarr").toArray();
testarr2.setValueAt(3, "ocho");
}
// orphan array append to test array
QJsArray orphanarr;
for (int i = 0; i < 3; i++)
{
QJsObject tempObj;
tempObj.setAttribute("id", i);
orphanarr.appendObject(tempObj);
}
testarr.appendArray(orphanarr);
QString strJSON = doc.toJson(QJsNode::Indented);
// print original
ui->plainTextEdit->setPlainText(strJSON);
哪个创造了这个:
{
"testarr": [
2,
4,
6,
"ocho",
{
"xxx": true,
"yyy": 8,
"zzz": 7.7999999999999998
},
[
{
"id": 0
},
{
"id": 1
},
{
"id": 2
}
]
],
"testobj": {
"attr1": "hola mundo",
"attr2": 3.1415999999999999,
"attr3": false,
"orphanobj": {
"A": 1,
"B": 2,
"C": 3
}
}
}