Which helper I can use to split this string?
-
I'm facing a lot of trouble parsing a simple YAML string. Here an example:
{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}}
My goal is to retrieve the two root objects:
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}
I'm using libYaml with the Qt wrapper. With this function I can retrieve the two root keys:
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; }
it outputs:
CR OL
But how to get the whole string?
This:qDebug() << (*i).as<QString>();
leads to:
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
How to use this wrapper to get the strings above?
Otherwise, how I can split the initial string into the two required? I'm not sure how to easily identify the comma that divides the two objects.... -
@Mark81
Funnily enough, although I have never used YAML, I was reading this week how it is a superset of JSON. I can relate to your string as though it were parseable as JSON. In that situation the values of your nodes are not strings orQString
s --- presumably hence your error message --- they are JSON/YAML objects. Look in your libYaml documentation for what type it uses for these "objects", and then look for a method on the object for serializing it as a string.Otherwise, how I can split the initial string into the two required? I'm not sure how to easily identify the comma that divides the two objects....
As an answer to that question:
QString::split("},")
orQString::split(QRegularExpression("}\\s*,"))
, would be a one-line dirty solution. Would I recommend it? No, it's not at all robust, and will only work if the input looks just like you show. But if all you want to do is split that particular input, you can't be bothered to do it properly and want a solution in 10 seconds, there you are! -
@Mark81
Understood. Then don't use the "split", which was beyond hacky anyway.I am finding no formal documentation of libYaml, we need to see what is available in the API? From looking at https://github.com/yaml/libyaml/blob/master/examples/mapping.yaml, does YAML/that library refer to what I called "objects" in JSON as mappings in YAML?
-
@Mark81
...which is what your "objects" contain, hence I was suggesting these are called "mappings" in YAML/libYaml and so what you should be looking up.-
I asked where you get the written documentation for libYaml (its API) from? Without that neither of us can know what code you need.
-
Why are you seeking the string-text of these (sub-)nodes? The libYaml parser is deserializing the string input. It will (almost certainly) not offer you access to the original, non-parsed text for each element. You will likely have to re-produce that from the parsed tree by serializing the individual nodes. And for all I know libYaml is a deserializer only and may not even offer that. Why can't you used the resulting parsed tree for the nodes instead of wanting to turn them back into text, which would be simpler?
-
-
@JonB The only "docs" I can find is the one you've already pointed out: https://github.com/yaml/libyaml. I neither can find more... I agree it's hard without, but of course if it was well-documented I would not post here :-)
I need the whole string for each root-object because I need to understand the type of content before deserializing them!
I defined a lot of "objects", each one starting with a specific key:CR: {...} AB: {...} SY: {...} ST: {...} HJ: {...}
They can be joined at root-level in one in-line YAML:
{CR: {...}, AB: {...}, ST: {...}}
Because they have different fields, for each one I wrote a deserializing function, example:
bool DBCCromoUtils::decodeCromoFade(QString yaml, int *color, int *panel, int *val, qreal *fade_in, qreal *fade_out) { QString command; YAML::Node root = YAML::Load(yaml.toStdString().c_str()); YAML::Node node = root["CR"]; if (node.IsNull()) return false; YAML::convert<QString>().decode(node["cmd"], command); if (command != "fade") return false; YAML::convert<int>().decode(node["color"], *color); YAML::convert<int>().decode(node["panel"], *panel); YAML::convert<int>().decode(node["value"], *val); YAML::convert<qreal>().decode(node["fin"], *fade_in); YAML::convert<qreal>().decode(node["fout"], *fade_out); return true; }
In order to work I need to pass to this function only the YAML portion that belong to this "object".
-
@Mark81 said in Which helper I can use to split this string?:
The only "docs" I can find is the one you've already pointed out: https://github.com/yaml/libyaml. I neither can find more...
Then I wish you all the best, because (politely) the only way to help you/solve your problem is to write the code and hack around with it to see what is going on and what the library offers, and you will have to do that. Or hope a libYaml expert pops by....
-
Hi,
Just in case, there's a Qt wrapper for libyaml that might be easier to use.
One thing that is not clear is why do you need the string representation to know how to deserialise the block ?
Usually, you structure should be well defined and thus you should either have the name of the mapping allowing to know what is inside it and thus use a dedicated function to extract the data you want or you should have a specific field in your structure that will again allow you to know to which function you want to send it for further processing.