Search code examples
c++yaml-cpp

yaml-cpp parsing nested maps and sequences error


I am trying to parse a file with nested maps and sequences which somewhat looks like this

annotations:
 - dodge:
   type: range based
   attributes:
    start_frame:
     frame_number: 25
     time_stamp: 2017-10-14 21:59:43
    endframe:
     frame_number: 39     
     time_stamp: 2017-10-14 21:59:45
    distances:
     - 2
     - 5
     - 6

I am getting an error saying Ensure the node exists. Below is my sample code.

YAML::Node basenode = YAML::LoadFile(filePath);

const YAML::Node& annotations = basenode["annotations"];

RangeBasedType rm;

for (YAML::const_iterator it = annotations.begin(); it != annotations.end(); ++it)
{
    const YAML::Node& gestures = *it;

    std::string type = gestures["type"].as<std::string>(); // this works

    rm.setGestureName(type);

    if (type == "range based")
    {
        const YAML::Node& attributes = gestures["attributes"];

        for (YAML::const_iterator ti = attributes.begin(); ti != attributes.end(); ++ti)
        {
            const YAML::Node& frame = *ti; 

            if (frame["start_frame"]) // this fails saying it is not a valid node
            {
                std::cout << frame["frame_number"].as<int>();

                rm.setStartFrame(frame["frame_number"].as<int>());
            }
        }
    }
}

I wish to get the frame_number from nodes start_frame and end_frame. I have checked the YAML format for validity. Any reasons on why this is not working?


Solution

  • This loop:

    for (YAML::const_iterator ti = attributes.begin(); ti != attributes.end(); ++ti)
    

    is iterating over a map node. Therefore, the iterator points to a key/value pair. Your next line:

    const YAML::Node& frame = *ti;
    

    dereferences it as a node. Instead, you need to look at its key/value nodes:

    const YAML::Node& key = ti->first;
    const YAML::Node& value = ti->second;
    

    yaml-cpp allows iterators to both point to nodes and key/value pairs because it can be a map or a sequence (or a scalar), and it's implemented as a single C++ type.