Reputation: 73
I am having an issue creating a config file for a class that includes a list of objects that implement the same interface when I use the YamlStream API.
I want to preserve the local tags that I put on list items so that they can be deserialized correctly from another context. In my actual project, I have to do some pre-processing on the YamlNodes. However, when I want to serialize the YamlDocument to a file, the local type tags are lost. I see that the tags are parsed when converted to a YamlStream (some nodes have the Tag property set appropriately). However, after processing, they are serialized without the tags.
I have some examples of what I have tried in this repo: https://github.com/mariotee/YamlDotNetIssue
var stream = new YamlStream();
stream.Load(new StringReader(yaml));
//pre processing would go here
using (var wr = new StringWriter())
{
stream.Save(wr, false);
File.WriteAllText("path", wr.ToString());
}
expected result:
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
actual result:
pets:
- name: skippy
likesMilk: true
- name: felix
likesMilk: true
- name: ralf
likesBones: true
- name: Hamtaro
likesTv: true
...
Upvotes: 1
Views: 516
Reputation: 12469
As I commented, this is a bug. However, you can work around it by providing your own implementation of IEmitter
and forcing the IsImplicit property of MappingStart to false:
public static void Main()
{
var yaml = @"
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
";
var stream = new YamlStream();
stream.Load(new StringReader(yaml));
stream.Save(new MappingFix(new Emitter(Console.Out)), false);
}
public class MappingFix : IEmitter
{
private readonly IEmitter next;
public MappingFix(IEmitter next)
{
this.next = next;
}
public void Emit(ParsingEvent @event)
{
var mapping = @event as MappingStart;
if (mapping != null) {
@event = new MappingStart(mapping.Anchor, mapping.Tag, false, mapping.Style, mapping.Start, mapping.End);
}
next.Emit(@event);
}
}
This produces the intended output:
pets:
- !Cat
name: skippy
likesMilk: true
- !Cat
name: felix
likesMilk: true
- !Dog
name: ralf
likesBones: true
- !Hamster
name: Hamtaro
likesTv: true
...
Note that this requires the latest release - YamlDotNet 6.1.1
Upvotes: 1