YamlDotNet深度合并两个YAML文件:库内是否有简便实现方式?
Does YamlDotNet have a built-in way to deep merge two YAML files?
Short answer—no, YamlDotNet doesn’t include a native API for deep merging two separate YAML files out of the box.
You mentioned the question about the merge key (<<), and that’s a common point of confusion. That feature is part of the YAML specification itself, not a YamlDotNet-specific tool for cross-file merging. It lets you reuse and merge structures within a single YAML file using anchors and references, like this:
default_config: &default timeout: 30 retries: 2 production_config: <<: *default retries: 5 endpoint: "prod.example.com"
YamlDotNet will parse this into a single merged object where production_config inherits timeout:30 and overrides retries to 5. But this only works if you structure your YAML files to use this syntax upfront—it doesn’t let you take two unrelated YAML files and merge their contents automatically.
Implementing Deep Merge for Two YAML Files
To merge two independent YAML files deeply, you’ll need to:
- Deserialize both files into a flexible data structure (like
Dictionary<object, object>) - Write a recursive function to merge the structures
- Serialize the merged result back to YAML
Here’s a complete example:
Step 1: Deserialize the YAML Files
using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; using System.IO; using System.Collections.Generic; // Set up the deserializer (adjust naming convention to match your YAML style) var deserializer = new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); // Load and deserialize first YAML file using var file1Reader = new StreamReader("config1.yaml"); var yamlData1 = deserializer.Deserialize<Dictionary<object, object>>(file1Reader); // Load and deserialize second YAML file using var file2Reader = new StreamReader("config2.yaml"); var yamlData2 = deserializer.Deserialize<Dictionary<object, object>>(file2Reader);
Step 2: Recursive Deep Merge Function
This function will merge yamlData2 into yamlData1, with these rules:
- Add new keys from
yamlData2toyamlData1 - Recursively merge nested dictionaries
- Append items from
yamlData2lists toyamlData1lists (adjust this logic if you need to replace or deduplicate) - Override existing non-dictionary/non-list values with
yamlData2values
void DeepMergeDictionaries(Dictionary<object, object> target, Dictionary<object, object> source) { foreach (var (key, sourceValue) in source) { if (!target.TryGetValue(key, out var targetValue)) { // Key doesn't exist in target—add it target[key] = sourceValue; continue; } // Both values are dictionaries: recurse if (targetValue is Dictionary<object, object> targetDict && sourceValue is Dictionary<object, object> sourceDict) { DeepMergeDictionaries(targetDict, sourceDict); } // Both values are lists: append source items to target else if (targetValue is IList targetList && sourceValue is IList sourceList) { foreach (var item in sourceList) { targetList.Add(item); } } // For all other types: override target value with source else { target[key] = sourceValue; } } } // Run the merge DeepMergeDictionaries(yamlData1, yamlData2);
Step 3: Serialize the Merged Result
var serializer = new SerializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); using var mergedFileWriter = new StreamWriter("merged_config.yaml"); serializer.Serialize(mergedFileWriter, yamlData1);
Customizing the Merge Logic
You can tweak the DeepMergeDictionaries function to fit your needs:
- Change list handling to replace instead of append
- Add deduplication logic for list items
- Skip certain keys from being overwritten
- Handle specific value types (like numbers, booleans) with custom rules
内容的提问来源于stack exchange,提问作者Dragouf

