Deserializing YAML into Custom Types

╄→гoц情女王★ 提交于 2019-12-06 01:43:08

问题


I'm currently trying to deserialize a YAML document into standard .NET objects, such as string for scalar values and Dictionary<string, object> for mappings, using YamlDotNet library.

I guess that Deserializer class is the best option, but its output is object and Dictionary<object>. I tried implementing custom INodeTypeResolver like this:

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;
    }
}

and using it like this:

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

but that doesn't seem to have any effect. Is there any way to change the type of objects produced by Deserializer?


回答1:


AFAIK, Deserialize takes a type parameter, which is really nice

%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."

...

can be Deserialized by

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

provided that MyMessage has a format and desc property, and provided that it's not in a namespace. If it is, you can either register it with the Deserializer beforehand, or create a new tag for it. The %TAG alias seems to eat the first character of the tag, so I put an underscore. Maybe a bug. The other way is to register it,

deserializer.RegisterTagMapping(
    "tag:yaml.org,2002:message", typeof(MyMessage));



回答2:


You're on the right track with INodeTypeResolver but you need to build and use a custom deserializer:

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


来源:https://stackoverflow.com/questions/23181376/deserializing-yaml-into-custom-types

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!