Retrieving a nested object inside a JSON string using rapidjson

34,857

Solution 1

You need to iterate through object's members manually, as GetString() only works on string members, while document["a"] is an Object. You need to iterate through that object's members using MemberIterator variable. I had no practice in C* for more than 15 years, so I can only give a general idea of how it should work:

for (MemberIterator m = document["a"].MemberBegin(); m != document["a"].MemberEnd(); ++m) {
    std::cout << m.name << " " << (m.IsNumber()?m.GetNumber():m.GetString()) << endl;
}

Also, you might want to look at Accept() method, it seems to return a JSON string of an object you give it.

Solution 2

If element is an object you can just access subproperties with []:

for (SizeType i = 0; i < layers.Size(); i++){   
  cout << layers[i]["name"].GetString() << endl;
}

Solution 3

There is another great approach realized in rapidjson - JSON Pointers. They have experimental status and according to the documentation shall be included in v.1.1. Anyway this approach looks like XPATH for XML so to get nested value we can use syntax like

Value* tmpValue = GetValueByPointer(doc, "/result/job/blob");

I tried this functionality and in my opinion this is better than iterators.

Share:
34,857
pparescasellas
Author by

pparescasellas

Updated on January 29, 2021

Comments

  • pparescasellas
    pparescasellas over 3 years

    I need to retrieve a nested object inside a JSON string and I'm trying to do it using rapidjson. All I've found is how to retrieve arrays and basic types, but not sub-objects. I have created the following toy example which gives an error:

    rapidjson::Document document;
    std::string test =  " { \"a\": { \"z\" : 21 } } ";
    std::cout << test << std::endl;
    if ( document.Parse<0>( test.c_str() ).HasParseError() ) {
        std::cout << "Parsing error" << std::endl;
    } else {
        if ( document[ "a" ].IsObject() ) {
            std::cout << "OK" << std::endl;
            std::cout << document[ "a" ].GetString() << std::endl;
        }
    }
    

    This is the output when executed:

    { "a": { "z" : 21 } } 
    OK
    JSONTest: ../rapidjson/document.h:441: const typename Encoding::Ch* rapidjson::GenericValue<Encoding, Allocator>::GetString() const [with Encoding = rapidjson::UTF8<char>, Allocator = rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>]: Assertion `IsString()' failed. Aborted
    

    How do I retrieve the inner object to continue my parsing? Thanks.

    Edit: What I need is to obtain the string representation of the inner object so I can call another function that is going to parse it.

    Edit 2: code that allows to retrieve the inner object as a string:

    rapidjson::Document document;
    std::string test =  "{\"a\":{\"z\":21}} ";
    if ( document.Parse<0>( test.c_str() ).HasParseError() ) {
        std::cout << "Error parsing" << std::endl;
    } else {
        if ( document[ "a" ].IsObject() ) {
            rapidjson::StringBuffer sb;
            rapidjson::Writer<rapidjson::StringBuffer> writer( sb );
            document[ "a" ].Accept( writer );
            std::cout << sb.GetString() << std::endl;
        }
    }