Как десериализовать YAML с помощью YAMLDotNet?

Я хочу десериализовать этот YAML с помощью YAMLDotNet.
Он имеет последовательность и вложенное сопоставление.

  • data.yml
people:
  - name: "John"
    age: 20
  - name: "Michael"
    age: 21
  - name: "William"
    age: 22

network:
  address: "192.168.1.1"
  port: 1234
  param:
    paramNumber: 10
    paramString: "text data"
    paramBool: true

Это мой код. Но он не может скомпилироваться. Я хотел бы знать следующие две вещи.

  1. Как определить класс для десериализации вложенного сопоставления?
  2. Как получить к нему доступ?
  • Печать десериализованных данных
DeserializedObject obj = YamlImporter.Deserialize("data.yml");

foreach(var people in obj.people)
{
    Console.WriteLine(people.name);
    Console.WriteLine(people.age);
}

Console.WriteLine(obj.network["address"]);
Console.WriteLine(obj.network["port"]);
/* how to access param? */
  • Код десериализатора (YAMLDotNet)
public class YamlImporter
{
    public static DeserializedObject Deserialize(string yamlName)
    {
        StreamReader sr = new StreamReader(yamlName);
        string text = sr.ReadToEnd();
        var input = new StringReader(text);
        var deserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
        DeserializedObject deserializeObject = deserializer.Deserialize<DeserializedObject>(input); /* compile error */
        return deserializeObject;
    }
}

public class DeserializedObject
{
    public List<People> people { get; set; }

    public class People
    {
        public string name { get; set; }
        public int age { get; set; }
    }

    public Dictionary<string, Network> network { get; set; }

    public class Network
    {
        public string address { get; set; }
        public int port { get; set; }
        public Dictionary<string, Param> param { get; set; }
    }

    public class Param
    {
        public int paramNumber { get; set; }
        public string paramString { get; set; }
        public bool paramBool { get; set; }
    }
}

Спасибо,


person ken    schedule 13.08.2020    source источник
comment
Network.port это int. Вы не можете индексировать в int.   -  person Aluan Haddad    schedule 13.08.2020
comment
@AluanHaddad О, это была небольшая ошибка. Спасибо! obj.port["port"] -> obj.network["port"]   -  person ken    schedule 13.08.2020
comment
Тем не менее, моя проблема все еще остается.   -  person ken    schedule 13.08.2020
comment
Ну, во-первых, param написано с ошибкой. Значение называется params в YAML. params — это ключевое слово в C#. Вы можете использовать его как имя свойства, добавив к нему префикс @: @params { get; set; }. Я не знаю, как вы ожидали, что это сработает с неправильным именем.   -  person Aluan Haddad    schedule 13.08.2020
comment
У вас также есть словари, которые не имеют смысла. @params должен быть типа Params, network должен быть типа Network   -  person Aluan Haddad    schedule 13.08.2020
comment
@AluanHaddad Спасибо, я поменяю params на param в YAML. Я думаю, что это может избежать ключевых слов.   -  person ken    schedule 14.08.2020
comment
@AluanHaddad Я наконец понял твой совет. Я удалю словарь сети и параметр. Это было ненужно. Это решило все мои проблемы. Благодарю вас!   -  person ken    schedule 14.08.2020
comment
Я рад, что у вас все получилось, но изменять данные из-за наличия ключевого слова на другом языке — плохая практика. Я бы остановился на @params. Причина, по которой вы можете префиксировать зарезервированные слова в C#, заключается в том, чтобы обрабатывать взаимодействие с другими языками, что и происходит. Кроме того, поскольку вы используете CamelCaseNamingConvention, вы можете использовать PascalCase для всех ваших свойств C#, позволяя вашему коду соответствовать языковым соглашениям, еще одной функции взаимодействия, в данном случае предоставляемой библиотекой YAMLDotNet.   -  person Aluan Haddad    schedule 14.08.2020


Ответы (1)


Совет @AluanHaddad помог мне решить мою проблему. Спасибо,

// How to access params? //
Console.WriteLine(obj.network.param.paramNumber);
Console.WriteLine(obj.network.param.paramString);
Console.WriteLine(obj.network.param.paramBool);
//public Dictionary<string, Network> network { get; set; }
public Network network { get; set; }

public class Network
{
    public string address { get; set; }
    public int port { get; set; }
    //public Dictionary<string, Param> param { get; set; }
    public Param param { get; set; }
}
person ken    schedule 14.08.2020