Search code examples
c++jsondictionarytreejsoncpp

How to Iterate through Collection without knowing the keys? and Later save those keys


My goal is to extract column heads from a Json file converted from a normal table in CSV (Excel sheet) using C++. I am using Visual Studio 2022 IDE.

My Json file looks like this

{
  "people" : [
    {
       "firstName": "Joe",
       "lastName": "Jackson",
       "gender": "male",
       "age": 28,
       "number": "7349282382"
    },
    {
       "firstName": "James",
       "lastName": "Smith",
       "gender": "male",
       "age": 32,
       "number": "5678568567"
    },
    {
       "firstName": "Emily",
       "lastName": "Jones",
       "gender": "female",
       "age": 24,
       "number": "456754675"
    }
  ]
}

I am using JsonCpp library for parsing.

So the goal here is to extract the column heads of the table (keys like "firstname","lastname" etc. in the given Json file) without knowing any of the keys (like if I use any other json file of same format but with different content).

Here is a snippet of my code

fstream file("smallTabularJson.json");

    Json::Reader reader;            //creating reader that will be used to parse
    Json::Value data;           //creating collection that will hold the parsed data

    reader.parse(file, data);       //parsing data from file and storing in 'data'

Here I have parsed the content of Json file into a collection named 'data'

The approach I am trying is

Since the json file looks like a STL Map, I will treat 'data' as a Map.

Create a map iterator to access the key "people" (without explicitly mentioning it) and go to its value which is an Array.

Go inside Array[0].

It is again an map then create another iterator to access its keys one by one and save every key into an vector.

Print the Vector.

But the problem is that the 'data' is not a Map. So when I tried this -

map<string, string>::iterator itr = data.begin();

It throws this error -

Error Code: E0312   
no suitable user-defined conversion from "Json::Value::iterator" to "std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string, std::string>>>>" exists    jsonFileRead3 "link to my directory"

Which means that 'data' is not a Map but Tree instead.

Please suggest how I can I convert 'data' from Tree to a Map, or if there is any other function inside JsonCpp library to get the keys. Thankyou


Solution

  • map<string, string>::iterator is specific to map<string, string>. A Json::Value has some conceptual similarities to that container, but it is not the same thing.

    data.begin() is a ValueIterator. For short, you can write

    auto itr = data.begin()
    

    And it will use the actual type of itr. An important thing here is to note that Json::ValueIterator has the following methods:

    Its key method returns a Json::Value that in your case will be a string representing the name of the key.

    If you want to get that as a std::string, you can use

    itr.key().asString();
    

    Its unary operator* method returns a reference to the Json::Value that is the value present at the key, which in your case will be of array type, which will need to be handled appropriately.