Search code examples
c++c++11for-loopyaml-cpp

Parse a YAML list of dictionaries in C++


I have the following yaml (a simplified version of my case):

---
my_list:
    - item1:
        name: name1
    - item2:
        name: name2

And then I am trying to parse it like this using C++ and YAML-CPP:

for (const auto & p : node["my_list"]) {
    std::cout << p.IsMap() << std::endl;
    YAML::Node key = p.first;
    YAML::Node value = p.second;
}

This apparently works (IsMap() returns 1), but as soon as I do: p.first.as<std::string>(); it crashes. How should I parse this?

On the contrary, if I do:

for (auto it = node.begin(); it != node.end(); ++it) {
    YAML::Node key = it->first;
    YAML::Node value = it->second;
    std::cout << key.as<std::string>() << std::endl;
}

And the output here is my_list, so I can continue the parsing.

My question is: how can I parse using the C++11 range for loop? Thanks


Solution

  • If you're iterating through a YAML sequence, the entries you get are the entries in the sequence, not key/value pairs:

    for (const auto& p : node["my_list"]) {
        std::cout << p.IsMap() << "\n";
        // Here 'p' is a map node, not a pair.
        for (const auto& key_value : p) {
          // Now 'key_value' is a key/value pair, so you can read it:
          YAML::Node key = key_value.first;
          YAML::Node value = key_value.second;
          std::string s = key.as<std::string>();
          // ....
        }
    }
    

    The reason that p has fields first and second is that iteration in yaml-cpp is overloaded: you can iterate through sequences (where the entries are nodes) or maps (where the entries are key/value pairs). In each case, the other's syntax is available statically, but won't give you any reasonable information at runtime.