且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

反序列化一个 YAML “表"数据的

更新时间:2023-02-18 22:53:02

正如其他答案所述,这是有效的 YAML.但是,文档的结构是特定于应用程序的,并没有使用 YAML 的任何特殊功能来表达表格.

As other answers stated, this is valid YAML. However, the structure of the document is specific to the application, and does not use any special feature of YAML to express tables.

您可以使用 YamlDotNet 轻松解析此文档.但是,您将遇到两个困难.第一个是,由于列的名称放在键内,您将需要使用一些自定义序列化代码来处理它们.第二个是您需要实现某种抽象才能以表格方式访问数据.

You can easily parse this document using YamlDotNet. However you will run into two difficulties. The first is that, since the names of the columns are placed inside the key, you will need to use some custom serialization code to handle them. The second is that you will need to implement some kind of abstraction to be able to access the data in a tabular way.

我已经提供了一个概念证明,将说明如何解析和读取数据.

I have put-up a proof of concept that will illustrate how to parse and read the data.

首先,创建一个类型来保存来自 YAML 文档的信息:

First, create a type to hold the information from the YAML document:

public class Document
{
    public List<Group> Groups { get; set; }
}

public class Group
{
    public string Name { get; set; }

    public IEnumerable<string> ColumnNames { get; set; }

    public IList<IList<object>> Rows { get; set; }
}

然后实现IYamlTypeConverter来解析Group类型:

public class GroupYamlConverter : IYamlTypeConverter
{
    private readonly Deserializer deserializer;

    public GroupYamlConverter(Deserializer deserializer)
    {
        this.deserializer = deserializer;
    }

    public bool Accepts(Type type)
    {
        return type == typeof(Group);
    }

    public object ReadYaml(IParser parser, Type type)
    {
        var group = new Group();

        var reader = new EventReader(parser);
        do
        {
            var key = reader.Expect<Scalar>();
            if(key.Value == "Name")
            {
                group.Name = reader.Expect<Scalar>().Value;
            }
            else
            {
                group.ColumnNames = key.Value
                    .Split(',')
                    .Select(n => n.Trim())
                    .ToArray();

                group.Rows = deserializer.Deserialize<IList<IList<object>>>(reader);
            }
        } while(!reader.Accept<MappingEnd>());
        reader.Expect<MappingEnd>();

        return group;
    }

    public void WriteYaml(IEmitter emitter, object value, Type type)
    {
        throw new NotImplementedException("TODO");
    }
}

最后,将转换器注册到反序列化器并反序列化文档:

Last, register the converter into the deserializer and deserialize the document:

var deserializer = new Deserializer();
deserializer.RegisterTypeConverter(new GroupYamlConverter(deserializer));

var document = deserializer.Deserialize<Document>(new StringReader(yaml));

您可以在此处测试完整工作的示例

这只是一个概念证明,但它应该作为您自己实施的指南.可以改进的地方包括:

This is only a proof of concept, but it should serve as a guideline for you own implementation. Things that could be improved include:

  • 检查和处理无效文件.
  • 改进Group 类.也许让它不可变,并添加一个索引器.
  • 如果需要序列化支持,则实现 WriteYaml 方法.
  • Checking for and handling invalid documents.
  • Improving the Group class. Maybe make it immutable, and also add an indexer.
  • Implementing the WriteYaml method if serialization support is desired.