如何用YamlDotNet动态反序列化可作为标量或序列的Pool字段
解决YamlDotNet中Pool字段多格式反序列化问题
针对你的场景——YAML文件中pool字段既可能是字符串标量,也可能是包含name的对象序列,可通过自定义YAML类型转换器实现动态反序列化,具体步骤如下:
1. 保留原有实体类结构
你的Jobs和Pool类无需大幅修改,保持原定义即可:
public class Jobs { [YamlMember(Alias = "job", ApplyNamingConventions = false, Order = 0)] public string Job { get; set; } [YamlMember(Alias = "displayName", ApplyNamingConventions = false, Order = 1)] public string DisplayName { get; set; } [YamlMember(Alias = "pool", ApplyNamingConventions = false, Order = 3)] public Pool Pool { get; set; } } public class Pool { [YamlMember(Alias = "name", ApplyNamingConventions = false, Order = 0)] public string Name { get; set; } }
2. 添加根实体类(匹配YAML根结构)
由于你的YAML根节点是Jobs数组,需新增一个根类来承接:
public class RootJobConfig { [YamlMember(Alias = "Jobs", ApplyNamingConventions = false)] public List<Jobs> JobsList { get; set; } }
3. 实现自定义类型转换器
创建PoolConverter类实现IYamlTypeConverter接口,处理两种格式的pool字段解析:
using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Serialization; public class PoolConverter : IYamlTypeConverter { // 指定该转换器处理Pool类型 public bool Accepts(Type type) { return type == typeof(Pool); } public object ReadYaml(IParser parser, Type type) { var pool = new Pool(); // 处理字符串标量格式(如pool: secondPool) if (parser.Current is Scalar scalar) { pool.Name = scalar.Value; parser.MoveNext(); } // 处理对象序列格式(如pool: - name: firstPool) else if (parser.Current is SequenceStart) { parser.MoveNext(); // 跳过序列起始标记 // 读取序列内的第一个映射对象 if (parser.Current is MappingStart) { parser.MoveNext(); // 跳过映射起始标记 // 定位到name字段 if (parser.Current is Scalar key && key.Value == "name") { parser.MoveNext(); if (parser.Current is Scalar value) { pool.Name = value.Value; parser.MoveNext(); } } parser.MoveNext(); // 跳过映射结束标记 } parser.MoveNext(); // 跳过序列结束标记 } return pool; } // 如需序列化可实现此方法,示例默认输出字符串格式 public void WriteYaml(IEmitter emitter, object value, Type type) { var pool = (Pool)value; emitter.Emit(new Scalar(pool.Name)); } }
4. 注册转换器并执行反序列化
构建反序列化器时添加自定义转换器,即可兼容两种YAML格式:
var deserializer = new DeserializerBuilder() .WithTypeConverter(new PoolConverter()) .Build(); // 读取YAML文件内容并反序列化 using var reader = new StreamReader("your-yaml-file.yaml"); var jobConfig = deserializer.Deserialize<RootJobConfig>(reader);
扩展说明
如果你的业务需要处理序列中多个pool对象的场景,可将Jobs类中的Pool属性改为List<Pool>,并调整转换器的ReadYaml逻辑,遍历序列中的所有映射对象并添加到集合中。
内容的提问来源于stack exchange,提问作者Saurabh Raoot
相关产品推荐
相关产品推荐

