Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I use this with multiple documents of arbitrary types? #848

Closed
attilam opened this issue Sep 15, 2023 · 3 comments
Closed

How do I use this with multiple documents of arbitrary types? #848

attilam opened this issue Sep 15, 2023 · 3 comments

Comments

@attilam
Copy link

attilam commented Sep 15, 2023

Given I have a few classes in C# that I want to deserialize into from a file with multiple YAML documents. How would I go about it? The only samples I've found conveniently work on documents with one known type, so they are of no help. The YAML file I work with could come with different documents in arbitrary order and type.

The SDK seems to work with magic functions I have no idea how/why to use and the source is too big to crawl through, I've tried.

It would be cool to have a sample on how to deserialize more complex YAML streams with multiple documents and types to deserialize into.

So I think what I'd need is something where I would set the classes that could come up in the YAML, and it would figure out which one needs to be instantiated for a given document. The sources seem to have some indication that this would be possible, but I'm wrecking my head over how it would work in practice.

E.g.:

public class Foo {
  public string FooA { get; set; }
  public string FooB { get; set; }
}

public class Bar {
  public string BarA { get; set; }
  public string BarB { get; set; }
}
---
BarA: alpha
BarB: beta
---
FooA: alpha
FooB: beta

Edit: For the time being I've hacked together this awful mess (based on some of the samples), which solves my immediate use case, it's awful, and it assumes a specific document order (first a "TrimmingPrefs", then any number of "Pages"), but I need to move on to other stuff, so it'll do 😅

var deserializer = new DeserializerBuilder()
    .WithNamingConvention(CamelCaseNamingConvention.Instance)
    .Build();
var parser = new Parser(new StringReader(yamlFile.text));

parser.Consume<StreamStart>();

while (parser.Accept<DocumentStart>(out var thing))
{
    if (prefs == null)
    {
        prefs = deserializer.Deserialize<TrimmingPrefs>(parser);
        Debug.Log("Got prefs");
    }
    else
    {
        var doc = deserializer.Deserialize<Page>(parser);
        pages.Add(doc);
    }
}
@EdwardCooke
Copy link
Collaborator

On your deserializerbuilder try using a type recriminatory based on existing keys and deserialize it to an object. My laptops having a lot of issues so I can’t put together an example code right now. I’ll hunt down the tests that show how to use it in a few minutes.

@EdwardCooke
Copy link
Collaborator

@attilam
Copy link
Author

attilam commented Sep 17, 2023

Thanks, I've updated my script with the version that implements an interface for the discriminator, and it seems to work fine 👍

var deserializer = new DeserializerBuilder()
    .WithNamingConvention(CamelCaseNamingConvention.Instance)
    .WithTypeDiscriminatingNodeDeserializer(options =>
    {
        options.AddUniqueKeyTypeDiscriminator<ITrimmingDoc>(
            new Dictionary<string, Type>()
            {
                { "link", typeof(Page) },
                { "speed", typeof(TrimmingPrefs) }
            });
    })
    .Build();

var parser = new Parser(new StringReader(yamlFile.text));

parser.Consume<StreamStart>();

while (parser.Accept<DocumentStart>(out var thing))
{
    ITrimmingDoc doc = deserializer.Deserialize<ITrimmingDoc>(parser);

    if (doc is TrimmingPrefs trimmingPrefs)
    {
        prefs = trimmingPrefs;
    }
    else if (doc is Page page)
    {
        pages.Add(page);
    }
    else
    {
        Debug.LogError("Unknown YAML doc");
    }
}

edit: copy-pasta mistake 🤦

@attilam attilam closed this as completed Sep 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants