YamlDotNet
YamlDotNet copied to clipboard
MergingParser Does not Merge Aliases
Code example
https://dotnetfiddle.net/Es32Or
var yaml = @"
object: &anchorName anchorValue
another: *anchorName";
var parser = new MergingParser(new Parser(new StringReader(yaml)));
while (parser.MoveNext())
{
Console.WriteLine(parser.Current);
}
Actual Output:
Stream start
Document start [isImplicit = True]
Mapping start [anchor = , tag = , isImplicit = True, style = Block]
Scalar [anchor = , tag = , value = object, style = Plain, isPlainImplicit = True, isQuotedImplicit = False]
Scalar [anchor = anchorName, tag = , value = anchorValue, style = Plain, isPlainImplicit = True, isQuotedImplicit = False]
Scalar [anchor = , tag = , value = another, style = Plain, isPlainImplicit = True, isQuotedImplicit = False]
Alias [value = anchorName]
Mapping end
Document end [isImplicit = True]
Stream end
Expected Output:
Stream start
Document start [isImplicit = True]
Mapping start [anchor = , tag = , isImplicit = True, style = Block]
Scalar [anchor = , tag = , value = object, style = Plain, isPlainImplicit = True, isQuotedImplicit = False]
Scalar [anchor = anchorName, tag = , value = anchorValue, style = Plain, isPlainImplicit = True, isQuotedImplicit = False]
Scalar [anchor = , tag = , value = another, style = Plain, isPlainImplicit = True, isQuotedImplicit = False]
**Scalar [anchor = anchorName, tag = , value = anchorValue, style = Plain, isPlainImplicit = True, isQuotedImplicit = False]**
Mapping end
Document end [isImplicit = True]
Stream end
Motivation
Sometimes it is useful to deserialize part of a document. This may be the case when the document is very large, when type information is not known until the document is being parsed. Currently, substituting Aliases is handled by AliasValueDeserializer
however this will not be able to resolve anchors which occur outside of the part of the document being parsed.
For example, consider the document:
products:
- &apple
name: Apple
cost: 1.25
sales:
- customer: pensono
items:
- *apple
Lets say this document is very large, so we would only like to deserilize the sales section. If only the sales section is deserialized, then *apple
won't be resolved.
Code example: https://dotnetfiddle.net/rpsPia
var yaml = @"
products:
- &apple
name: Apple
cost: 1.25
sales:
- customer: pensono
items:
- *apple
";
var deserializer = new DeserializerBuilder().Build();
var parser = new MergingParser(new Parser(new StringReader(yaml)));
parser.Consume<StreamStart>();
parser.Consume<DocumentStart>();
parser.Consume<MappingStart>();
while (parser.TryConsume<Scalar>(out var section))
{
// Only deserialize the sales section
if (!section.Value.Equals("sales"))
{
parser.SkipThisAndNestedEvents();
continue;
}
var sales = deserializer.Deserialize<List<object>>(parser); // This line throws "AnchorNotFoundException: Anchor 'apple' not found"
Console.WriteLine(sales.Count);
}