Search code examples
yamldotnet

Is it possible to disallow duplicates in YAML file?


I'm using YamlDotNet to parse simple configuration files (no deep nesting, etc.). The deserializer will parse strings containing duplicate fields, overwriting earlier values. For example,

foo: bar
foo: baz

is considered equivalent to

foo: baz

For my application, I would prefer that such duplicates cause an exception to be thrown. Is this possible?


Solution

  • The default node deserializers use the indexer to assign values. One way to achieve the desired behavior is to deserialize to a type that does not allow duplicate values, such as:

    public class UniqueKeysDictionary<TKey, TValue>
        : Dictionary<TKey, TValue>
        , IDictionary<TKey, TValue>
    {
        TValue IDictionary<TKey, TValue>.this[TKey key]
        {
            get { return base[key]; }
            set { base.Add(key, value); }
        }
    }
    

    A fully working example can be found here.

    One significant issue with this solution is that it violates the contract of the indexer, whose behavior should be to overwrite the value.

    Another approach would be to replace the implementation of GenericDictionaryNodeDeserializer with one that uses the Add() method instead of the indexer. This is the relevant portion of a different example that shows how to replace a node deserializer:

    var deserializer = new Deserializer();
    
    var objectDeserializer = deserializer.NodeDeserializers
        .Select((d, i) => new {
            Deserializer = d as ObjectNodeDeserializer,
            Index = i
        })
        .First(d => d.Deserializer != null);
    
    deserializer.NodeDeserializers[objectDeserializer.Index] =
        new ValidatingNodeDeserializer(objectDeserializer.Deserializer);