2015-05-28 40 views
1

我使用YamlDotNet来解析简单的配置文件(没有深层嵌套等)。反序列化器将解析包含重复字段的字符串,覆盖较早的值。例如,是否可以在YAML文件中禁止重复?

foo: bar 
foo: baz 

被视为等同于

foo: baz 

对于我的申请,我宁愿这样的重复导致引发异常。这可能吗?

回答

0

默认节点反序列化器使用索引器来分配值。达到预期的行为的一种方法是反序列化的类型不允许重复的值,如:

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

该解决方案的一个重要问题是它违反了contract of the indexer,其行为应该是覆盖该值。

另一种方法是将GenericDictionaryNodeDeserializer的实现替换为使用Add()方法而不是索引器的方法。这是一个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); 
+0

感谢您的详细答复,并编写这个库。我得到了第二种工作方式。这有点棘手,因为我的GenericUniqueDictionaryNodeDeserializer,它是GenericDictionaryNodeDeserializer与您建议的单行更改,使用YamlDotNet.Serialization.Utilities.ReflectionUtility和YamlDotNet.ReflectionExtensions由于保护级别无法访问的一些代码,所以我不得不复制那也是。 – MJD

0

存在涉及棉绒一个解决方案,但我不相信这将是相关 你,因为它不会导致异常在YamlDotNet抛出。无论如何,我会发布它 ,因为它可以避免替换 GenericDictionaryNodeDeserializer的实施。

这是yamllint命令行工具:

sudo pip install yamllint 

具体来说,它有一个规则key-duplicates检测重复键:

$ cat test.yml 
foo: bar 
foo: baz 

$ yamllint test.yml 
test.yml 
    2:1  error duplication of key "foo" in mapping (key-duplicates) 
相关问题