Десериализация YAML в пользовательские типы

В настоящее время я пытаюсь десериализовать документ YAML в стандартные объекты .NET, такие как string для скалярных значений и Dictionary<string, object> для сопоставлений, используя библиотеку YamlDotNet.

Я предполагаю, что класс Deserializer — лучший вариант, но его вывод — object и Dictionary<object>. Я попытался реализовать пользовательский INodeTypeResolver следующим образом:

class MyNodeTypeResolver : INodeTypeResolver
{
    bool INodeTypeResolver.Resolve(NodeEvent nodeEvent, ref Type currentType)
    {
        if (currentType == typeof(object))
        {
            if (nodeEvent is SequenceStart)
                currentType = typeof(List<object>);
            else if (nodeEvent is MappingStart)
                currentType = typeof(Dictionary<string, object>);
            else if (nodeEvent is Scalar)
                currentType = typeof(string);

            return true;
        }

        return false;
    }
}

и используя его так:

Deserializer deserializer = new Deserializer();
deserializer.TypeResolvers.Add(new MyNodeTypeResolver());
var res = deserializer.Deserialize(input);

но это, кажется, не имеет никакого эффекта. Есть ли способ изменить тип объектов, создаваемых Deserializer?


person mavsic    schedule 20.04.2014    source источник


Ответы (2)


Насколько мне известно, Deserialize принимает параметр типа, что очень удобно.

%YAML 1.1
%TAG !namespace! _MyNamespace.NestedClass.Whatever.
---

entry_0: !namespace!MyMessage
  format: Alert
  desc: "Entry One! Uses the exact string representation of the desired type. (A bit fragile, IMHO)"

entry_1: !!message
  format: Default
  desc: "Entry Two! Uses a type registered beforehand."

entry_2:
  format: Default
  desc: "Entry Three! Just winging it, sometimes YamlDotNet is exceedingly clever."

...

может быть десериализован с помощью

var dict = new Deserializer().Deserialize<Dictionary<string,MyMessage>>(
    new StringReader(that_doc_up_there));

при условии, что MyMessage имеет свойство format и desc и при условии, что оно не находится в пространстве имен. Если это так, вы можете либо зарегистрировать его в Deserializer заранее, либо создать для него новый тег. Псевдоним %TAG, похоже, съедает первый символ тега, поэтому я поставил подчеркивание. Может ошибка. Другой способ - зарегистрировать его,

deserializer.RegisterTagMapping(
    "tag:yaml.org,2002:message", typeof(MyMessage));
person Ben Scott    schedule 26.08.2015

Вы на правильном пути с INodeTypeResolver, но вам нужно создать и использовать собственный десериализатор:

DeserializerBuilder deserializerBuilder = new DeserializerBuilder()
    .WithNodeTypeResolver(new MyNodeTypeResolver());
IDeserializer deserializer = deserializerBuilder.Build();
var res = deserializer.Deserialize(input);
person Nick    schedule 07.07.2019