YamlDotNet不支持KeyValuePair反序列化,求特定场景替代方案
解决YamlDotNet反序列化为IEnumerable<KeyValuePair<string, string>>的方案
针对无法改用Dictionary<string, string>,且YamlDotNet默认不支持KeyValuePair<,>类型反序列化的场景,以下是几个可行方案:
方案1:自定义YAML类型转换器
实现IYamlTypeConverter接口,专门处理KeyValuePair<string, string>的反序列化逻辑,再将转换器注册到反序列化器中。
using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Serialization; public class KeyValuePairConverter : IYamlTypeConverter { public bool Accepts(Type type) { return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>) && type.GetGenericArguments()[0] == typeof(string) && type.GetGenericArguments()[1] == typeof(string); } public object ReadYaml(IParser parser, Type type) { parser.Consume<MappingStart>(); var key = parser.Consume<Scalar>().Value; var value = parser.Consume<Scalar>().Value; parser.Consume<MappingEnd>(); return new KeyValuePair<string, string>(key, value); } public void WriteYaml(IEmitter emitter, object value, Type type) { var kvp = (KeyValuePair<string, string>)value; emitter.Emit(new MappingStart()); emitter.Emit(new Scalar(kvp.Key)); emitter.Emit(new Scalar(kvp.Value)); emitter.Emit(new MappingEnd()); } }
使用示例:
var deserializer = new DeserializerBuilder() .WithTypeConverter(new KeyValuePairConverter()) .Build(); var yaml = @" - key1: value1 - key2: value2 - key3: value3 "; var result = deserializer.Deserialize<IEnumerable<KeyValuePair<string, string>>>(yaml);
方案2:通过中间类型转换
先将YAML反序列化为List<Dictionary<string, string>>,再通过LINQ转换为目标类型,无需自定义转换器,逻辑直观:
var deserializer = new DeserializerBuilder().Build(); var yaml = @" - key1: value1 - key2: value2 - key3: value3 "; var intermediate = deserializer.Deserialize<List<Dictionary<string, string>>>(yaml); var result = intermediate.SelectMany(dict => dict).AsEnumerable();
方案3:自定义INodeDeserializer
如果需要更底层的反序列化控制,可实现INodeDeserializer接口扩展YamlDotNet的核心反序列化逻辑:
using YamlDotNet.Core; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NodeDeserializers; public class KeyValuePairNodeDeserializer : INodeDeserializer { private readonly INodeDeserializer innerDeserializer; public KeyValuePairNodeDeserializer(INodeDeserializer innerDeserializer) { this.innerDeserializer = innerDeserializer; } public bool Deserialize(IParser parser, Type expectedType, Func<IParser, Type, object> nestedObjectDeserializer, out object value) { if (expectedType.IsGenericType && expectedType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>) && expectedType.GetGenericArguments()[0] == typeof(string) && expectedType.GetGenericArguments()[1] == typeof(string)) { parser.Consume<MappingStart>(); var key = (string)nestedObjectDeserializer(parser, typeof(string)); var val = (string)nestedObjectDeserializer(parser, typeof(string)); parser.Consume<MappingEnd>(); value = new KeyValuePair<string, string>(key, val); return true; } return innerDeserializer.Deserialize(parser, expectedType, nestedObjectDeserializer, out value); } }
使用示例:
var deserializer = new DeserializerBuilder() .WithNodeDeserializer(inner => new KeyValuePairNodeDeserializer(inner)) .Build(); var yaml = @" - key1: value1 - key2: value2 - key3: value3 "; var result = deserializer.Deserialize<IEnumerable<KeyValuePair<string, string>>>(yaml);
内容的提问来源于stack exchange,提问作者Salih Kavaf
相关产品推荐
相关产品推荐

