I am using YamlDotNet library, and I wanted to deserialize the 1000s of Yaml file using a common data structure class. Sample class have given below. The class Jobs contains a filed Pool which can be scalar or sequence. Like it can be string or object, How to deserialize it dynamically based on pool.
public class Jobs
{
[YamlMember(Alias = "job", ApplyNamingConventions = false, Order = 0)]
public string Job { get; set; }
[YamlMember(Alias = "displayName", ApplyNamingConventions = false, Order = 1)]
public string DisplayName { get; set; }
[YamlMember(Alias = "pool", ApplyNamingConventions = false, Order = 3)]
public Pool Pool { get; set; }
}
public class Pool
{
[YamlMember(Alias = "name", ApplyNamingConventions = false, Order = 0)]
public string Name { get; set; }
}
Many files are like
Jobs:
- job: Job1
displayName: DisplayName1
pool:
- name: firstPool
and other files are like
Jobs:
- job: Job2
displayName: DisplayName2
pool: secondPool
How to deserialize yaml files dynamically based on pool as pool can be string or object.
Based on your examples, it seems you want to allow the following two things:
You can solve this by providing your own implementations of
IYamlTypeConverter. Once defined, the converters can be easily registered while constructing the deserializer:I have recently written such adapters in one of my open source projects.
The List Adapter
For the list aspect, declare a YAML type converter as a generic class with item type
T. In itsAcceptsmethod, indicate it can handleIEnumerable<T>or similar basic list types, based on your data model.You then have to check whether you are looking at the start of a sequence. If so, read the sequence, and collect the items one by one. Otherwise, just read the single element and act as if you had read a sequence with just one element.
In both cases, you can call a YAML deserializer again, which should contain all of your type converters except for the one you are in to prevent an infinite recursion.
Note that the results are passed to a private method called
CreateReturnValue- the implementation of this method basically depends on what list types you want to support in your data model. If you just have arrays, return an array, but if you have some properties of typeT[], some of typeList<T>, or even others, you may have to instantiate different collections based on the target type.You'll have to register an instance of this converter type for each of the item types you wish to support when constructing your deserializers.
The Object Adapter
The type converter for individual objects is simpler, but depends on the object type, as you have to specify how to create an object based on a scalar value.
Once again, create a deserializer with all of your converters except the one you are in.
The above example assumes you wish to read objects of type
MyObject(which you also have to indicate in theAcceptsmethod), which can be instantiated by passing a string scalar to the constructor.