Handling errors
editCatch YAML errors
Every error of the content, from invalid YAML to a value that does not match its type, throws a YamlException or a derived class. Start and End give the position of the node at fault:
static string? Validate(string yaml)
{
try
{
YamlSerializer.Deserialize<Product>(yaml);
return null;
}
catch (YamlException exception)
{
// Line and Column are zero-based
return $"line {exception.Start.Line + 1}, column {exception.Start.Column + 1}";
}
}
Assert.Null(Validate("Id: 1"));
Assert.Equal("line 2, column 7", Validate("Id: 1\nTags: 3"));
Assert.Equal("line 1, column 5", Validate("Id: [1"));- Line and Column start at
0: add1to show them to a user. Index is the position of the character in the text. - SyntaxErrorException and SemanticErrorException derive from YamlException and report YAML that is not valid, such as an unclosed
[or an unsupported%YAMLversion. Catch YamlException to handle every error of the content. - An exception thrown by a callback is wrapped in a YamlException.
Other exceptions report a problem in your code rather than in the YAML, and are not meant to be caught: a NotSupportedException for a type that cannot be serialized, an InvalidOperationException for an invalid configuration of your types, such as two members with the same key.
Name the file in the messages
Set SourceName, typically to the path of the file, to start the messages with it:
var options = new YamlSerializerOptions { SourceName = "config.yaml" };
var exception = Assert.Throws<YamlException>(() => YamlSerializer.Deserialize<Product>("Id: [1, 2]", options));
Assert.Equal("config.yaml: (Lin: 0, Col: 4, Chr: 4) - (Lin: 0, Col: 4, Chr: 4): Expected a Scalar token but found 'StartSequence'.", exception.Message);The message gives the start and end positions as (Lin, Col, Chr), from 0. YamlException.SourceName returns the name.
Read without exceptions
TryDeserialize returns false instead of throwing a YamlException:
if (YamlSerializer.TryDeserialize<Product>("Id: 1", out var value))
{
Assert.Equal(1, value!.Id);
}
Assert.False(YamlSerializer.TryDeserialize<Product>("Id: not a number", out _));It does not tell what is wrong: use it when invalid input is expected and its cause does not matter, and catch the exception when you report the error.