Skip to content

Stream style parsing returns strings for nulls #1053

@GunArm

Description

@GunArm

YamlDotNet 16.3.0

Describe the bug
I'm not very experienced with YAML, but (according to references like https://ref.coddy.tech/yaml/yaml-null-values) my understanding is that a key like foo: should produce a null value, not an empty string.

While the typed deserializer behaves accordingly, YamlStream (and company) interpret these null-like forms as strings, not null. This includes:

  • key:"" (should be null)
  • key: null"null" (should be null)
  • key: ~"~" (should be null)

To Reproduce
The following tests demonstrate the issue. The first test uses the typed deserializer and behaves correctly. The second uses YamlStream and fails:

[Fact]
public void TypedDeserializer_ParsesKeyWithNoValueAsNull()
{
    // Arrange
    var yaml = "Key:";
    var deserializer = new DeserializerBuilder().Build();

    // Act
    var result = deserializer.Deserialize<Dummy>(yaml);

    // Assert
    Assert.Null(result.Key);
}
private class Dummy { public string? Key { get; set; } }
[Fact]
public void YamStream_ParsesKeyWithNoValueAsNull()
{
    // Arrange
    var yaml = "Key:";
    var stream = new YamlStream();
    stream.Load(new StringReader(yaml));

    // Act
    var root = (YamlMappingNode)stream.Documents[0].RootNode;
    var node = root.Children[new YamlScalarNode("Key")];
    var scalar = Assert.IsType<YamlScalarNode>(node);

    // Assert
    // This will fail — scalar.Value is "" instead of null
    Assert.Null(scalar.Value);
}

I'm currently mitigating this in my conversion from YamlDotNet output to my own object by explicitly converting the strings returned with this switch case:

YamlScalarNode scalar when new[] { "", "~", "null" }.Contains(scalar.Value) && scalar.Style == ScalarStyle.Plain => null

This lets actual quoted empty strings through as strings. It handles my known cases, but I might be missing others. I assume the intention was not to return those as strings, particularly since the typed deserializer returns null.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions