查找所有键JSON-RapidJSON

时间:2019-04-11 09:31:31

标签: c++ rapidjson

我需要使用RapidJSON库在kTypeNames []中找到所有键。 尝试迭代所有节点,但我遗漏了一些东西;这是代码:

#include <iostream>
#include <fstream>
#include <string>
#include <bits/stdc++.h>
#include <unistd.h>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

using namespace rapidjson;

using namespace std;

const char* kTypeNames[] = { "id", "text", "templ_text", "key" };

int main(int argc, char* argv[]) {

string line;
char json[65000];
std::ifstream file(argv[1]);
unsigned long i = 0;
if (file.is_open()) {
    while (!file.eof()) {
        file.get(json[i]);
        i++;
    }
    file.close();
} else {
    cout << "Unable to open file";
}

Document document;
document.Parse(json);
printf("\n\n\n\n*********Access values in document**********\n");

assert(document.IsObject());

for (auto Typename : kTypeNames) {
    if (document.HasMember(Typename)) {

        cout << "\n";
        cout << Typename << ":" << document[Typename].GetString()<< endl;
        cout << "\n";
    }
    else {
        cout << "\n None\n";
    }
 }

它不适用于嵌套的JSON。

{
"node": {
    "text": "find this",
    "templ_text": "don't find",
    "ver": "don't find"
},
"ic": "",
"text": "also this",
"templ_text": "don't care",
"par": {
    "SET": {
        "vis": "<blabla>",
        "text": "keyFound",
        "templ_text": "don't need this"
    }
}
}

这是输出:

None
text:also this
templ_text:don't care
None

我想找到所有的“文本”键 我该如何遍历所有的nodes / json文档?

1 个答案:

答案 0 :(得分:1)

您拥有的代码只是直接在文档根目录内搜索预定义键的列表(document.HasMember不是递归搜索!)。

您可以递归遍历文档节点。例如,对于对象/地图节点,您可以在MemberBegin()MemberEnd()迭代器上循环,类似于std::map或其他标准容器。

for (auto i = node.MemberBegin(); i != node.MemberEnd(); ++i)
{
    std::cout << "key: " << i->name.GetString() << std::endl;
    WalkNodes(i->value);
}

数组使用Begin()End()。然后,当遇到带有“文本”成员的节点时,可以输出该节点的值(i->value)。

或者,您可以使用解析器流来执行此操作,而不是使用Document DOM对象。 Rapidjson为此使用了一个“推送” API,它会在遇到每个JSON时调用您在类中定义的方法。具体来说,它将调用Key方法。

class MyHandler : public BaseReaderHandler<UTF8<>, MyReader> {
    bool Key(const char* str, SizeType length, bool copy)
    {
        std::cout << "Key: " << str << std::endl;
    }
    ...
};
MyHandler handler;
rapidjson::Reader reader;
rapidjson::StringStream ss(json);
reader.Parse(ss, handler);

这有点复杂,您将需要设置某种标志,然后在其后输出下一个值回调。

class MyHandler : public BaseReaderHandler<UTF8<>, MyReader> {
    bool Key(const char* str, SizeType length, bool copy)
    {
        isTextKey = strcmp(str, "text") == 0; // Also need to set to false in some other places
        return true;
    }
    bool String(const char* str, SizeType length, bool copy)
    {
        if (isTextKey) std::cout << "text string " << str << std::endl;
        return true;
    }
    ...

    bool isTextKey = false;
};

还请记住,JSON允许在字符串\0中使用null,这就是为什么还具有size参数和成员以及Unicode的原因。因此,要完全支持任何需要考虑的JSON文档。