我使用YamlDotNet来解析简单的配置文件(没有深层嵌套等)。反序列化器将解析包含重复字段的字符串,覆盖较早的值。例如,是否可以在YAML文件中禁止重复?
foo: bar
foo: baz
被视为等同于
foo: baz
对于我的申请,我宁愿这样的重复导致引发异常。这可能吗?
我使用YamlDotNet来解析简单的配置文件(没有深层嵌套等)。反序列化器将解析包含重复字段的字符串,覆盖较早的值。例如,是否可以在YAML文件中禁止重复?
foo: bar
foo: baz
被视为等同于
foo: baz
对于我的申请,我宁愿这样的重复导致引发异常。这可能吗?
默认节点反序列化器使用索引器来分配值。达到预期的行为的一种方法是反序列化的类型不允许重复的值,如:
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);
存在涉及棉绒一个解决方案,但我不相信这将是相关 你,因为它不会导致异常在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)
感谢您的详细答复,并编写这个库。我得到了第二种工作方式。这有点棘手,因为我的GenericUniqueDictionaryNodeDeserializer,它是GenericDictionaryNodeDeserializer与您建议的单行更改,使用YamlDotNet.Serialization.Utilities.ReflectionUtility和YamlDotNet.ReflectionExtensions由于保护级别无法访问的一些代码,所以我不得不复制那也是。 – MJD