3

Suppose I have the following YAML:

config_one:
  name: foo
  stuff: value

config_two:
  name: bar
  random: value

I want to selectively parse config_one into an object and I want config_two to be ignored:

class ConfigOne
{
  public string Name {get;set;}
  public string Stuff {get;set;}
}

How can I do this? The documentation is pretty lacking, or at least, it uses a lot of terminology that doesn't make much sense to me, and thus I was not able to search for this functionality.

void.pointer
  • 24,859
  • 31
  • 132
  • 243
  • See this question: [YamlDotNet - need deserializer to ignore extra nodes or be okay with missing nodes](https://stackoverflow.com/q/44470352) – greenjaed Mar 30 '21 at 23:08
  • I may have unintentionally asked a two part question. The second part being that I need to parse `config_one` YAML into `ConfigOne` C# object. Even if I use the ignore members method you linked to, I still can't do `Deserialize()`. – void.pointer Mar 30 '21 at 23:56

2 Answers2

2

When building your deserializer, add IgnoreUnmatchedProperties():

var deserializer = new DeserializerBuilder()
    .WithNamingConvention(UnderscoredNamingConvention.Instance)
    .IgnoreUnmatchedProperties()
    .Build();

This "Instructs the deserializer to ignore unmatched properties instead of throwing an exception."
Git Source

greenjaed
  • 589
  • 8
  • 20
  • The remaining challenge is how to tell the library to map class `ConfigOne` to `config_one` in YAML. The `YamlMember` attribute doesn't work on classes. Not sure how else to do it. Thank you for your help. Maybe expand your example to include `deserializer.Deserialize?>()` – void.pointer Mar 30 '21 at 23:45
  • Normally when deserializing a config file like yaml, you have a class that represents the entire file which contains objects representing each item in the file. So, in your case you would wrap `ConfigOne` in a Config Class like this: `Class Config { public ConfigOne ConfigOne { get; set; } }`. Then, you would deserialize `Config`. – greenjaed Mar 31 '21 at 00:10
  • Thanks, I personally dislike that for certain design reasons. I guess I'll build a generic wrapper object for parsing purposes and then move the internal `ConfigOne` out. I wish there was a better way to process YAML in piecemeal. Overall I haven't been pleased with YamlDotNet but there do not seem to be any better options, which is surprising to me, honestly. – void.pointer Mar 31 '21 at 00:16
0

With Cinchoo ETL - an open source library, you can load selective nodes using YamlPath with reader object.

Here is the working sample

string yaml = @"
config_one:
  name: foo
  stuff: value

config_two:
  name: bar
  random: value
";
using (var r = ChoYamlReader<ConfigOne>.LoadText(yaml)
    .WithYamlPath("config_one")
    )
{
    foreach (var rec in r)
        Console.WriteLine(rec.Dump());
}

Or one liner code

    Console.WriteLine(ChoYamlReader.DeserializeText<ConfigOne>(yaml, "config_one").FirstOrDefault().Dump());

Output:

-- ChoYamlReaderTest.Program+ConfigOne State --
        Name: foo
        Stuff: value

Sample fiddle: https://dotnetfiddle.net/oMzL3R

Disclaimer: I'm author of this library.

Cinchoo
  • 6,088
  • 2
  • 19
  • 34