Tencent / rapidjson

A fast JSON parser/generator for C++ with both SAX/DOM style API
http://rapidjson.org/
Other
14.21k stars 3.53k forks source link

Retriving the path of the keys in a json #1239

Open AVV86 opened 6 years ago

AVV86 commented 6 years ago

Hello , I am trying to write a code to get the keys and the path of the key which can be used further in another function.I am able to get the keys in the json , but I am unable to retrieve the path of those keys.I need the path of the keys to avoid the recursion in further implementation.

    class test {
    public:
    static bool parseJson(const string &temp) {
    Document d;
    d.Parse(temp.c_str());
    getKeyPath(d);
     }

static void getKeyPath(const Value &json) {
    for (Value::ConstMemberIterator itr = json.MemberBegin(); itr != json.MemberEnd(); itr++) {
        cout << itr->name.GetString() << endl;

        if (itr->value.GetType() == kObjectType) {

            for (Value::ConstMemberIterator itr1 = itr->value.MemberBegin();
                 itr1 != itr->value.MemberEnd(); itr1++) {

                if (itr1->value.GetType() == kObjectType) {

                    getKeyPath(itr1->value);
                } else if (itr1->value.GetType() == kArrayType) {
                    for (auto itr2 = itr1->value.Begin(); itr2 != itr1->value.End(); itr2++) {

                        if (itr2->GetType() == kArrayType || itr2->GetType() == kObjectType) {

                            getKeyPath(*(itr2));
                        }
                    }
                }
            }
        } else if (itr->value.GetType() == kArrayType) {

            for (Value::ConstValueIterator itr1 = itr->value.Begin(); itr1 != itr->value.End(); itr1++) {
                // cout << itr->name.GetString() << endl;
                if (itr1->GetType() == kArrayType || itr1->GetType() == kObjectType) {
                    // cout << itr->name.GetString() << endl;
                    getKeyPath(*(itr1));
                    //cout<<(itr1)<<endl;
                }
            }
        }
    }
}

};

    int main() {
    const char *temp = "{    \"glossary\": {        \"title\": \"example glossary\",        \"GlossDiv\": {            
    \"title\": \"S\",           \"GlossList\": {                \"GlossEntry\": {                    \"ID\": \"SGML\",                   
    \"SortAs\": \"SGML\",                   \"GlossTerm\": \"Standard Generalized Markup 
    Language\",                 \"Acronym\": \"SGML\",                  \"Abbrev\": 
    \"ISO 8879:1986\",                  \"GlossDef\": {                        \"para\": \"A meta- 
    markup language, used to create markup languages such as DocBook.\",                         
    \"GlossSeeAlso\": [\"GML\", \"XML\"]                    },                  \"GlossSee\": \"markup\"                
     }   }   }  }}";
     test::parseJson(temp);
      }

Json file

  {
  "glossary": {
    "title": "example glossary",
    "GlossDiv": {
        "title": "S",
        "GlossList": {
            "GlossEntry": {
                "ID": "SGML",
                "SortAs": "SGML",
                "GlossTerm": "Standard Generalized Markup Language",
                "Acronym": "SGML",
                "Abbrev": "ISO 8879:1986",
                "GlossDef": {
                    "para": "A meta-markup language, used to create markup languages such as DocBook.",
                    "GlossSeeAlso": ["GML", "XML"]
                },
                "GlossSee": "markup"
            }
        }
      }
   }
 }

Output keys

These are the keys whose real path I want to retrive glossary title GlossList ID SortAs GlossTerm Acronym Abbrev GlossDef GlossSee

Note : This is just a sample json but the json that will be received is unknown to me , so i have to get the keys and key path of that json .

miloyip commented 6 years ago

I tried to use JSON Pointer in rapidjson to implement what you may want:

#include "rapidjson/pointer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>

using namespace rapidjson;

void DumpPointers(const Value& v, const Pointer& parent) {
    if (v.IsObject())
        for (Value::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
            DumpPointers(itr->value, parent.Append(itr->name.GetString(), itr->name.GetStringLength()));
    else if (v.IsArray())
        for (SizeType i = 0; i < v.Size(); i++)
            DumpPointers(v[i], parent.Append(i));
    else {
        StringBuffer sb;
        parent.Stringify(sb);
        std::cout << sb.GetString() << std::endl;
    }
}

int main() {
    const char *temp = "{    \"glossary\": {        \"title\": \"example glossary\",        \"GlossDiv\": {            \"title\": \"S\",           \"GlossList\": {                \"GlossEntry\": {                    \"ID\": \"SGML\", \"SortAs\": \"SGML\",                   \"GlossTerm\": \"Standard Generalized Markup Language\",                 \"Acronym\": \"SGML\",                  \"Abbrev\": \"ISO 8879:1986\",                  \"GlossDef\": {                        \"para\": \"A meta- markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\"]                    },                  \"GlossSee\": \"markup\"}   }   }  }}";
    Document d;
    d.Parse(temp);

    Pointer root;
    DumpPointers(d, root);
}

Output:

/glossary/title
/glossary/GlossDiv/title
/glossary/GlossDiv/GlossList/GlossEntry/ID
/glossary/GlossDiv/GlossList/GlossEntry/SortAs
/glossary/GlossDiv/GlossList/GlossEntry/GlossTerm
/glossary/GlossDiv/GlossList/GlossEntry/Acronym
/glossary/GlossDiv/GlossList/GlossEntry/Abbrev
/glossary/GlossDiv/GlossList/GlossEntry/GlossDef/para
/glossary/GlossDiv/GlossList/GlossEntry/GlossDef/GlossSeeAlso/0
/glossary/GlossDiv/GlossList/GlossEntry/GlossDef/GlossSeeAlso/1
/glossary/GlossDiv/GlossList/GlossEntry/GlossSee
AVV86 commented 6 years ago

Thank you @miloyip . One more question , Can the pointer be used to retrieve value directly from the json without iterating?