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
?
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));
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