.net YamlDotNet不支持反序列化KeyValuePair< ,>类型

2cmtqfgy  于 2023-05-23  发布在  .NET
关注(0)|答案(1)|浏览(132)

我有一个场景,需要将一系列Map反序列化为IEnumerable<KeyValuePair<string, string>>,而简单地使用Dictionary<string, string>无法解决这个问题。显然,YamlDotNet不支持开箱即用的KeyValuePair<,>,那么我可以依靠什么替代解决方案呢?
示例YAML:

- key1: value1
- key2: value2
- key3: value3
xoefb8l8

xoefb8l81#

根据YamlDotNet的所有者aubry的说法,issue here声明KeyValuePair<,>不受支持,也不会受到支持。然而,他在同一问题下的回应中进一步指出,通过添加自定义INodeDeserializer可以轻松实现。但是,由于他所包含的示例不适用,我将在这里提供一个更准确的实现。

using System;
using System.Collections.Generic;

using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;

internal class KeyValuePairNodeDeserializer : INodeDeserializer
{
    public bool Deserialize(IParser parser, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, out object value)
    {
        if (expectedType.IsGenericType && expectedType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
        {
            parser.Consume<MappingStart>();

            var pairArgs = expectedType.GetGenericArguments();

            object key = null;
            object val = null;

            if (parser.Accept<Scalar>(out _))
                key = nestedObjectDeserializer(parser, pairArgs[0]);

            if (parser.Accept<Scalar>(out _))
                val = nestedObjectDeserializer(parser, pairArgs[1]);

            value = Activator.CreateInstance(expectedType, key, val);

            parser.Consume<MappingEnd>();
            return true;
        }

        value = null;
        return false;
    }
}

现在您可以注册您的自定义INodeDeserializer如下:

var deserializer = new DeserializerBuilder()
    .WithNodeDeserializer(new KeyValuePairNodeDeserializer())     // Register here.
    .WithNamingConvention(UnderscoredNamingConvention.Instance)
    .Build();

相关问题