将列表隐藏为 YamlDotNet 中具有自定义名称的对象

问题描述 投票:0回答:1

我正在尝试获取对象列表并将它们序列化为对象而不是列表,对象名称将来自对象的属性。

我遇到的问题是我可以让它工作,但我必须手动遍历对象上的所有属性。

我想知道是否有一些内置的方法可以做到这一点?

所以我有

public class Config
{
   public List<Component> Components { get; set; }
}

public class Component
{
   public string Name { get; set; }
   public string OtherProperties { get; set; }
}

然后我希望它的输出看起来像这样

Components:
  nameFromObjectProperty:
    OtherProperties: ""
  nameOfOtherComponent:
    OtherProperties: ""
c# yamldotnet
1个回答
0
投票

作为一个选项,您可以实现自定义转换器:

public sealed class ComponentConverter : IYamlTypeConverter
{
    private IValueSerializer ValueSerializer { get; } =
        new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).BuildValueSerializer();

    private IValueDeserializer ValueDeserializer { get; } =
        new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).BuildValueDeserializer();

    public bool Accepts(Type type) => type == typeof(Component);

    public object ReadYaml(IParser parser, Type type)
    {
        parser.Consume<MappingStart>();

        var name = (string)ValueDeserializer
            .DeserializeValue(parser, typeof(string), new SerializerState(), ValueDeserializer);
        var otherProperties = (Dictionary<string, string>)ValueDeserializer
            .DeserializeValue(parser, typeof(Dictionary<string, string>), new SerializerState(), ValueDeserializer);
        var component = new Component
        {
            Name = name,
            OtherProperties = otherProperties["OtherProperties"],
        };

        parser.Consume<MappingEnd>();

        return component;
    }

    public void WriteYaml(IEmitter emitter, object value, Type type)
    {
        emitter.Emit(new MappingStart());

        var result = (Component)value;
        ValueSerializer.SerializeValue(emitter, result.Name, typeof(string));
        ValueSerializer.SerializeValue(
            emitter,
            new Dictionary<string, string>()
            {
                ["OtherProperties"] = result.OtherProperties
            },
            typeof(Dictionary<string, string>));

        emitter.Emit(new MappingEnd());
    }
}

用途:

var components = new[] {
    new Component()
    {
        Name = "a",
        OtherProperties = "b",
    },
    new Component()
    {
        Name = "c",
        OtherProperties = "d",
    },
};

var serializer = new SerializerBuilder()
    .WithNamingConvention(CamelCaseNamingConvention.Instance)
    .WithTypeConverter(new ComponentConverter())
    .Build();
    
var yaml = serializer.Serialize(components);
Console.WriteLine(yaml);

var componentConverter = new ComponentConverter();
var deserializer = new DeserializerBuilder()
    .WithNamingConvention(CamelCaseNamingConvention.Instance)
    .WithTypeConverter(new ComponentConverter())
    .Build();

var deserializedComponents = deserializer.Deserialize<Component[]>(yaml);

Console.WriteLine(deserializedComponents);
© www.soinside.com 2019 - 2024. All rights reserved.