How to use yaml-cpp to emit a complicated data structure?
This question is targeted principally at the author of yaml-cpp (Jesse Beder), who has requested questions regarding yaml-cpp usage be posted here.
In a number of locations, including the yaml-cpp documentation, http://code.google.com/p/yaml-cpp/wiki/HowToEmitYAML#Using_Existing_Nodes
you have mentioned that yaml-cpp does not provide a way to modify existing YAML::Node objects in-memory, and your suggestions for modifying YAML in-memory are:
Use my own data structure to store the YAML in memory, and then somehow feed it back to yaml-cpp when serializing (which essentially boils down to reimplementing the polymorphism in YAML::Node, and is not much different from reimplementing much of yaml-cpp), or
"currentl开发者_运维百科y the best way to do this is to use the Emitter and pick-and-choose from your node's children", i.e. the example given in the documentation. The problem with that approach is that it works well only for the simplest cases. Suppose I want to add an element to a sequence of maps, where one of the elements of the map is itself a list? This can get arbitrarily complicated very quickly! Finding where to insert the new data, emitting the manipulators, this all has to be done "by hand".
To compound the problem, the Emitter is a formatter and its only output is a string, so my only option is to emit the entire YAML document with my modifications and then re-parse it anew into a new in-memory representation. If I am making many changes to the document, the efficiency footprint of this operation adds up quickly.
I understand that modifying an existing Node has implementational challenges (what do you do with existing references to the Node's data, or child Nodes' data?). However, it would seem to me that allowing new, freestanding Nodes to be created on-the-fly and inserted into the in-memory tree should at least be straightforward. This is, for example, how JsonCpp is implemented: http://jsoncpp.sourceforge.net
This would at least enable the "Emitter" approach that you document to be a potentially viable workaround, if inefficient.
I would appreciate your thoughts on these issues. Unfortunately these limitations are quite severe, and given that yaml-cpp is the only C++/OO YAML library out there, I wonder whether there is a practical alternative besides switching to JSON.
Thank you very much in advance for your thoughts!
However, it would seem to me that allowing new, freestanding Nodes to be created on-the-fly and inserted into the in-memory tree should at least be straightforward.
I'd like to do this (and I've looked at JsonCpp here), but there are three problems:
There's a difference between YAML and JSON: YAML distinguishes between a null node and a node that doesn't exist.
The current behavior of yaml-cpp is to throw an exception when a non-existent node is requested.
In YAML, mappings can have arbitrary keys.
For problem #2, it means it's likely we'll have to (majorly!) break the current behavior, which makes me hesitate to pull the trigger.
For example, in JsonCpp, when you write
root["encoding"];
it will create a default node for you if it doesn't exist. In yaml-cpp, it'll throw an exception if it doesn't exist. People may be relying on code that looks like:
try {
root["encoding"]; // etc
catch(const YAML::Exception&) {
// does not exist
}
Finally, for problem #3, how would you specify a key that's a mapping? And if someone wrote
root[1] = 5;
would that instantiate root
as a sequence with a null first element, or a mapping with a single key/value pair {1, 5}
? If it's the latter (which seems more natural), then
root[0] = 3;
root[1] = 5;
and
root[1] = 5;
root[0] = 3;
would have different behaviors, which would be counterintuitive.
Basically, the bottom line is that I've thought about this, but I haven't been able to come up with a good enough API for it. I'd love to do it, so if you have any thoughts, please let me know.
That said, I'm not sure if stackoverflow is the best place for a discussion like this (I wrote that on the yaml-cpp site because lots of people were posting how-to questions on the wikis) - so feel free to send me an email (it's on my user page).
精彩评论