Javi
Javi

Reputation: 3610

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

Upvotes: 2

Views: 3803

Answers (1)

Jesse Beder
Jesse Beder

Reputation: 34054

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.

Upvotes: 2

Related Questions