Search code examples
c#deserializationuser-defined-typesyamldotnet

YamlDotNet and custom types


I am discovering yaml and yamldotnet. Sorry if this is a pretty basic question:

  • does it make any sense to define user-defined types in yaml using the single exclamation mark such as:

    red: !color { red: 255, green: 0, blue: 0 }

  • How is this deserialized by YamlDotNet? In other words is there a way to ensure that the type color is mapped to a corresponding Color type in .net?

  • From my understanding of the following example https://dotnetfiddle.net/HD2JXM, YamlDotNet uses an implicit correspondence between the yaml document and the .net class to map yaml properties the corresponding class properties (as shown in the example, this can be customized with annotations). However no type checking is done.

To further clarify things. I have the following yaml document, which corresponds to a set of widgets:

controls:
  - Button:
      id: 1
      text: Hello Button World
  - Label:
      id: 2
      text: Hello Label World
  - TextView:
      id: 3
      content: >
        This is some sample text that will appear
        in a text view.

And I want to map it to a corresponding type hierarchy in c#:

class AOPage
{
    public IList<AOControl> Controls { get; set; }

}

class AOControl 
{
    public int Id { get; set;}
}

class AOLabel : AOControl
{
    public String Text { get; set;}
}

class AOButton : AOControl
{
    public String Text { get; set;}
}

class AOTextView : AOControl
{
    public String Contents{ get; set;}
}

Note that there is a similar question poster here: Using custom type resolver, which has not been answered.

Thanks!


Solution

  • If you do not specify a tag, the deserializer uses type information from the object graph that is being deserialized.

    In order to do what you want with YamlDotNet, the easiest way is to use a local tag, let's say !!color, then register a tag mapping for that tag:

    deserializer.RegisterTagMapping("tag:yaml.org,2002:color", typeof(Color));
    

    You can see a working example in the DeserializeCustomTags unit test.