yaml-cpp
yaml-cpp copied to clipboard
Empty map artifact impedes formatting of subsequent writes
Description
When you have a file with a map containing a list and you delete the last key in this map, an empty map artifact {} remains in the file. When you later load the file again by instantiating a new node and write to the file, this empty artifact seems to affect the formatting of the file.
How to reproduce
Here is an example that will reproduce the error. Make sure to have an empty testyaml.yaml file at the location where the filePath points to.
#include <cstdio>
#include "yaml-cpp/yaml.h"
#include <fstream>
#include <iostream>
int main() {
std::string filePath("testyaml.yaml");
YAML::Node data = YAML::LoadFile(filePath);
std::ofstream fout;
std::vector<std::string> stringData;
stringData.push_back("a_new_value");
// step 1: write a map with a nested list
std::cout<< "Before step 1: First we write a new list nested in a map to an empty file. Press enter to continue." << std::endl;
std::cin.get();
if (stringData.size() != 0) {
for (std::string str: stringData) {
data["my_key"].push_back(str);
}
}
fout.open(filePath);
fout << data;
fout.close();
// step 2: delete the map
std::cout<< "After step 1: We've written the map. The formatting is correct. Now we delete the last key in the map. Press enter to continue." << std::endl;
std::cin.get();
if (data["my_key"]) {
data.remove("my_key");
}
fout.open(filePath);
fout << data;
fout.close();
// step 3: repeat step 1
std::cout<< "After step 2: The last key in the map was deleted and the file was saved. There is an empty map artifact. Now we write a new value with the same method as before with a new node. Press enter to continue." << std::endl;
std::cin.get();
YAML::Node data2 = YAML::LoadFile(filePath); // load the written file with a new node
if (stringData.size() != 0) {
for (std::string str: stringData) {
data2["my_key"].push_back(str);
}
}
fout.open(filePath);
fout << data2;
fout.close();
std::cout<< "After step 3: Even though there is a list nested in a map with the correct keys, the formatting is corrupted." << std::endl;
}
The different stages of the .yaml file:
- Before step 1: The file is empty.
- After step 1 (writing the map):
my_key:
- a_new_value
- After step 2 (deleting the map):
{}
- After step 3 (repeating step 1):
{my_key: [a_new_value]}
Expected vs. actual behavior
The expected behavior would be that deleting the last key in the last map would result in an empty file. A subsequent write would then create a nicely formatted file, similar to that which is created after step 1.
The actual behavior shows that deleting the last key in the last map results in a non-empty file, leaving an empty map artifact.
A subsequent write results in logically correct content, but the formatting is not correct.
Further notes
The behavior does not occur if you execute step 3 with the same node that was used for step 1.
I assume that this is the case because instantiating the node again reads the actual file again, not using the internally stored context in the initially created node.
Another way to reproduce:
YAML::Node config(YAML::NodeType::Map);
std::ofstream fout("out.yaml");
fout << config;
fout.close();