Click here to Skip to main content
16,015,414 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am developing a C++ application that uses rapidjson to access information from a file that is in json format.

This file has a structure like the following:


{
  "field_1"        : "val_1",
  "field_2"        : "val_2",

  "section_1"      : {
       "field_11"  : 1,
       "field_12"  : "one text",
       "field_13"  : ["one", "two", "three"]
  },

  "section_2": {
       "field_21"  : [ 1, 2, 3, 4, 5 ],
       "field_22"  : true,
       "field_23"  : 3.14,
       "field_24"  : [ 1.00, 2.00, 3.00],
       "field_25"  : [ true, false, true ]
  },
}


The name of the fields is not fixed or known a priori. I need to obtain a vector with the name of all the fields there are in the json.

For example, something like this:

<pre>std::vector <std::string> json_fields;

json_fields = [ "field_1", "field_2", "section_1", "field_11", "field_12", 
"field_13", "section_2", "field_21", "field_22", , "field_21", "field_22",
"field_23", "field_24",, "field_25" ]




Or something similar, so that the C++ application can know what name the fields that have been defined in the json have, since its name is not known a priori.

Is it possible to do this with rapidjson?

Any comments or suggestions are welcome.



What I have tried:

I am able to get the value from a field using rapidjson if I know its name, but I will not know the names and I need to get the names.

I have read some tutorial that explain how to get the value of a field in the json or how to modify it, but they do not explain if it is possible to get the list with all names and how to get this.
Posted

1 solution

Looking at the documentation for rapidJSON[^], it looks like something like the following might work:
C++
std::vector<std::string> getAllKeys(const rapidjson::Value& object, const std::string& prefix = "") {
  std::vector<std::string> keys;

  for (rapidjson::Value::ConstMemberIterator jsonIterator = object.MemberBegin(); jsonIterator != object.MemberEnd(); ++jsonIterator) {
    std::string currentKey = prefix + jsonIterator->name.GetString();
    keys.push_back(currentKey);

    if (jsonIterator->value.IsObject()) {
      std::vector<std::string> subKeys = getAllKeys(jsonIterator->value, currentKey );
      keys.insert(keys.end(), subKeys.begin(), subKeys.end());
    } else if (jsonIterator->value.IsArray()) {
      for (rapidjson::SizeType index = 0; index < jsonIterator->value.Size(); ++index) {
        if (jsonIterator->value[index].IsObject()) {
          std::vector<std::string> subKeys = getAllKeys(jsonIterator->value[index], currentKey + "[" + std::to_string(index) + "].");
          keys.insert(keys.end(), subKeys.begin(), subKeys.end());
        }
      }
    }
  }
  return keys;
}
I've bodged this together based on a similar approach I've used in C# so I think the theory is sound. I've tried to use what I think are appropriate types for this library but you might have to play around with these. Of course, you are facing a fundamental issue with this in that a vector is a flat structure but JSON is nested so you are getting things that don't make sense in isolation.
 
Share this answer
 
Comments
Member 15796760 13-Jul-24 6:32am    
Thanks, I have tried this solution in C++ and it wroks right.
Pete O'Hanlon 13-Jul-24 6:56am    
I'm glad I could help.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900