0

Given this yaml:

{CR: {cmd: fade, color: blue, panel: 0, value: 30, fout: 0.5, fint: 5},OL: {cmd: text, value: Blu at 30% on all, color: white, time: 5, position: [540,100], size: 50}}

With this code:

bool SEMTools::decodeYaml(QString yaml)
{
    try
    {
        YAML::Node root = YAML::Load(yaml.toStdString().c_str());
        YAML::Node::iterator i;
        for (i = root.begin(); i != root.end(); i++)
        {
            qDebug() << (*i).first.as<QString>();
        }
        return true;
    }
    catch (YAML::TypedBadConversion<QString> const &e)
    {
        qDebug() << e.what();
    }

    return false;
}

I'm able to retrieve the lead keys: CR and OL. For each one I also need to retrieve the whole object:

CR: {cmd: fade, color: blue, panel: 0, value: 30, fout: 0.5, fint: 5}

and

OL: {cmd: text, value: Blu at 30% on all, color: white, time: 5, position: [540,100], size: 50}

I tried with:

qDebug() << (*i).as<QString>();

but my application crashes with this error:

terminate called after throwing an instance of 'YAML::InvalidNode'
  what():  invalid node; this may result from using a map iterator as a sequence iterator, or vice-versa

What is the right syntax to get the strings above?

Mark
  • 4,338
  • 7
  • 58
  • 120

1 Answers1

1

(*i).first is the key, (*i).second is its value.

Therefore, (*i) is the whole object as you call it (key + value). It's simply not a string, which is why you can't retrieve it via .as<QString>(). Each the key and the value are a YAML::Node just like root, and you can do .as<QString>() only on the key because it's a string. On the value, you can do (*i).second["cmd"].as<QString>() etc.

If you want the value to be a string instead of a nested YAML structure, you shouldn't input it as nested YAML structure.

flyx
  • 35,506
  • 7
  • 89
  • 126
  • Got it. Perhaps the problem is in my approach. The YAML comes from a third-part application. Because each key define the actual content (value) I need to know in advance the key in order to forward the value to the appropriate decoding function. – Mark Dec 19 '21 at 13:23
  • Of course I can do all inside the same function with a loooong list of `if`... but I thought it was more elegant to just find out the key and call the related function passing the value to be decoded appropriately. – Mark Dec 19 '21 at 13:24
  • @Mark That would work with your approach: You already did retrieve the key as `QString`, now you can either have branching where you call different functions based on the value of the key, or you use an `std:unordered_map` (or whatever Qt supplies for this use-case) with the strings as keys and function pointers as values for faster dispatching. In both cases, you'd just pass the key's value to the function. – flyx Dec 19 '21 at 13:40
  • In other words, instead of passing the value as string I'll pass it as `YAML::Node`. It makes sense indeed! – Mark Dec 19 '21 at 17:21