Comments

What steps will reproduce the problem?
AML::Node config = YAML::LoadFile("config.yaml");
config["lastLogin"] = getCurrentDateTime();
std::ofstream fout("config.yaml");
fout << config;
What is the expected output? What do you see instead?
It would be nice if we could maintain the order of Nodes in
saving/output-streaming.
What version of the product are you using? On what operating system?
0.3.0 on Ubuntu 11.x
Please provide any additional information below.
While we save/output-stream the order of Nodes in original files were not
maintained. It would be really nice if we could maintained original order
because most of the time we also do manual edit on yaml files and grouping some
variables together makes more sense.

Original issue reported on code.google.com by rudrapou...@gmail.com on 26 Jul 2012 at 11:33

This comment has been minimized.

This is sorta intentional. YAML doesn't specify the ordering of key/value pairs
in a map, so you're not supposed to rely on it.
However, I do see some value to it, so I will consider it. I'm just not
convinced yet :)

Original comment by jbe...@gmail.com on 29 Jan 2013 at 2:23

Changed state: Accepted

Added labels: Priority-Low, Type-Enhancement

Removed labels: Priority-Medium, Type-Defect

This comment has been minimized.

The way I see it, yaml-cpp is a tool for parsing files. A file is a (ordered)
sequence of information. This is especially true with YAML as it is meant to be
streamable. Therefore a YAML parser should somehow keep this information.
Of course there is the issue of creating a non-standard behavior people might
start relying on, and the issue of implementation overhead to keep the ordering
while still allowing fast search for keys.
Your suggestion to turn it into a sequence of single-element maps is not a bad
one. I'll consider it.

Original comment by oster.t...@gmail.com on 29 Jan 2013 at 7:04

Added labels: ****

Removed labels: ****

This comment has been minimized.

I appreciate that it's a potentially useful thing to do; but yaml-cpp is a tool
to parse YAML, which does not specify the ordering of key/value pairs in a map.
(A related situation: yaml-cpp also does not preserve stray whitespace. It is
*not* a goal of the library to be able to write a file exactly as it read it.)
The fact that YAML is streamable is a red herring - the YAML spec *explicitly*
says that key order is an implementation detail
(http://www.yaml.org/spec/1.2/spec.html#id2765608).
Again, though, this is one of those things that I do see some value in, so I'll
think about it. One problem is that some people want to maintain order and
others want it to be ordered alphabetically, and I'm not a huge fan of
proliferation of configuration details.

This comment has been minimized.

There's already a struct Mark that tells you a location in a file.
You can change
NodeBuilder::OnScalar/NodeBuilder::OnSequenceStart/NodeBuilder::OnMapStart by
uncommenting "mark" from the parameters and telling "node" to save the "mark".
To tell the node to save the mark, you will need to add a new member variable
"mark" to node_data and implement getters/setters up the chain (node_ref,
detail::node, Node).
If you want Clone() to work, you will also need to change NodeEvents::Emit to
pass in the actual mark instead of constructing an empty mark.

This comment has been minimized.

I also would like more ordered output. I fully get that YAML is using unordered
maps, but it's very weird when hand-editting YAML files, and each object is in
a different order.
Example:
YAML::Node root;
for(const auto &pair : this->Details.MaterialDetails)
{
Engine::MaterialID materialID = pair.first;
const Engine::MaterialDetails &materialDetails = pair.second;
YAML::Node material;
material["MaterialID"] = materialID;
material["DisplayName"] = materialDetails.displayName;
material["SoundID"] = materialDetails.soundID;
root["Materials"].push_back(material);
}
I find it really odd that iterating over elements in my map, each element of
the map will have its members outputted arbitrarily from one another.
Materials:
- DisplayName: Fallthrough
SoundID: 0
MaterialID: 2
- SoundID: 0
DisplayName: Default
MaterialID: 1
- MaterialID: 0
DisplayName: None
SoundID: 0
Each element is in a different order. I don't expect the elements in any
particular order, but a consistent order would be nice. Maybe you can output
mapped values by alphabetical (or numerical) order of the key, or some other
arbitrary-but-consistent order?

This comment has been minimized.

Yes, consistent output is what I'm asking for, not consistent iteration. The
iteration of 'MaterialDetails' in my example above is an std::unordered_map not
yaml-cpp, sorry for the confusion.
I was trying to demonstrate that outputting while in any kind of loop still
produces unordered (but correct) output, despite using the exact same functions
in the exact same order. Which you're aware of.

This comment has been minimized.

I would be interested in this as well, since it has forced me to use the "old"
Emitter API. In my mind, YAML should be easily readable, and arbitrary or
inconsistent ordering hinders that.
That said, the old Emitter API does the trick.

This comment has been minimized.

This is a high priority for me. I will have to figure out a workaround before I can proceed.

The config files read and written by yaml-cpp are committed to a git repo, and our company does code reviews of all changes. Because yaml-cpp writes maps in an unpredictable order, every time the config file is written, then entire file appears to change even if no content is different. This will make reviews unfeasible.

For my use case, I just need repeatable ordering, not controllable ordering. I'm imagining a new Emitter manipulator called SortedMaps or something.

This unnatural order removes that "human friendly" part of the data serialization process. In my config file I have some 20 main map entries, each one being itself a map of 5 to 20 entries. The resulting file could be manually edited much faster if order is preserved, just because one knows where to look for the items and the mapping order makes human sense.

Yes, "YAML doesn't specify the ordering of key/value pairs in a map, so you're not supposed to rely on it". Neither C++ ISO/IEC 14882:2011 specify some form of code indentation, yet we rely heavely on it for code readability.