How to write a map to a YAML file in Dart
It's a bit late of a response but for anyone else looking at this question I have written this class. It may not be perfect but it works for what I'm doing and I haven't found anything wrong with it yet. Might make it a package eventually after writing tests.
class YamlWriter { /// The amount of spaces for each level. final int spaces; /// Initialize the writer with the amount of [spaces] per level. YamlWriter({ this.spaces = 2, }); /// Write a dart structure to a YAML string. [yaml] should be a [Map] or [List]. String write(dynamic yaml) { return _writeInternal(yaml).trim(); } /// Write a dart structure to a YAML string. [yaml] should be a [Map] or [List]. String _writeInternal(dynamic yaml, { int indent = 0 }) { String str = ''; if (yaml is List) { str += _writeList(yaml, indent: indent); } else if (yaml is Map) { str += _writeMap(yaml, indent: indent); } else if (yaml is String) { str += "\"${yaml.replaceAll("\"", "\\\"")}\""; } else { str += yaml.toString(); } return str; } /// Write a list to a YAML string. /// Pass the list in as [yaml] and indent it to the [indent] level. String _writeList(List yaml, { int indent = 0 }) { String str = '\n'; for (var item in yaml) { str += "${_indent(indent)}- ${_writeInternal(item, indent: indent + 1)}\n"; } return str; } /// Write a map to a YAML string. /// Pass the map in as [yaml] and indent it to the [indent] level. String _writeMap(Map yaml, { int indent = 0 }) { String str = '\n'; for (var key in yaml.keys) { var value = yaml[key]; str += "${_indent(indent)}${key.toString()}: ${_writeInternal(value, indent: indent + 1)}\n"; } return str; } /// Create an indented string for the level with the spaces config. /// [indent] is the level of indent whereas [spaces] is the /// amount of spaces that the string should be indented by. String _indent(int indent) { return ''.padLeft(indent * spaces, ' '); }}
Usage:
final writer = YamlWriter();String yaml = writer.write({ 'string': 'Foo', 'int': 1, 'double': 3.14, 'boolean': true, 'list': [ 'Item One', 'Item Two', true, 'Item Four', ], 'map': { 'foo': 'bar', 'list': ['Foo', 'Bar'], },});File file = File('/path/to/file.yaml');file.createSync();file.writeAsStringSync(yaml);
Output:
string: "Foo"int: 1double: 3.14boolean: truelist: - "Item One" - "Item Two" - true - "Item Four"map: foo: "bar" list: - "Foo" - "Bar"
I ran into the same issue and ended up hacking together a simple writer:
// Save the updated configuration settings to the config file void saveConfig() { var file = _configFile; // truncate existing configuration file.writeAsStringSync(''); // Write out new YAML document from JSON map final config = configToJson(); config.forEach((key, value) { if (value is Map) { file.writeAsStringSync('\n$key:\n', mode: FileMode.writeOnlyAppend); value.forEach((subkey, subvalue) { file.writeAsStringSync(' $subkey: $subvalue\n', mode: FileMode.writeOnlyAppend); }); } else { file.writeAsStringSync('$key: $value\n', mode: FileMode.writeOnlyAppend); } }); }