Search code examples
c++jsonjsoncpp

How to fix JsonCPP error from getMemberNames()?


The JSON file looks like this:

{
"strings": [
    {
        "key_one": "value_one!"
    },
    {
        "key_two": "value_two!"
    },
    ]
}

The C++ file looks like this:

Json::Value root;
Json::Reader reader;
bool parsingSuccessful = reader.parse(contents, root);
const Json::Value strings = root["strings"];
std::vector<std::string> list = strings.getMemberNames();

The error caused by "strings.getMemberNames()" is:

Assertion failed: (type_ == nullValue || type_ == objectValue), function getMemberNames, file /projects/.../jsoncpp.cpp,

strings is an arrayValue, I confirmed it by getting it's ValueType = 6.


Solution

  • As you say, strings is an array, not an object. You need to either : (i) convert your strings json to be an object.

    {
    "strings": {
            "key_one": "value_one!",
            "key_two": "value_two!"
        }
    }
    

    In which case your existing code will be fine. This is what I'd do if you have control over the json you're parsing.

    or (ii) Iterate over the strings array - I'd only do this if the json is specified by some thrid party - It will look something like this:

    std::vector<std::string> all_keys;
    for ( int index = 0; index < strings.size(); ++index ) {
        std::vector<std::string> cur_keys = strings[index].getMemberNames();
        all_keys.insert( all_keys.end(), cur_keys.begin(), cur_keys.end() );
    }
    

    However actually using the values in all_keys to access anything in the strings array later is going to be painful - so you might want to store the key-value pairs in a map.

    std::map<std::string,std::string> key_values;
    for ( int index = 0; index < strings.size(); ++index ) {
        std::vector<std::string> cur_keys = strings[index].getMemberNames();
        for( int j=0; j<cur_keys.size(); ++j )
          key_values[cur_keys[j]] = ...
    }
    

    Or at least store the index of the strings array where the key was found.

    std::vector<std::pair<int,std::string> > all_keys;    std::vector<std::string> all_keys;
    for ( int index = 0; index < strings.size(); ++index ) {
        std::vector<std::string> cur_keys = strings[index].getMemberNames();
        for( int j=0; j<cur_keys.size(); ++j )
          all_keys.push_back( std::make_pair(index, cur_keys[j] ) );
    }