-
-
Notifications
You must be signed in to change notification settings - Fork 477
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
YamlDotNet doesn't respect non-nullable types #763
Comments
Can you provide example yaml and classes? If you can provide that, I'll look in to it. The nullable (question mark) on the classes is a compiler feature, not a runtime requirement, so suddenly instantiating a class and setting it using that instead of null may be considered a breaking change, I'd probably put that behind a feature flag. As for value types, if you declare a value type as nullable using |
public class MyClass
{
public string SomeString { get; set; }
public string? SomeNullableString { get; set; }
public bool IsGood { get; set; }
public bool IsNotGood { get; set; }
public bool IsDefinitelyNotGood { get; set; }
} SomeString: null
SomeNullableString: null
IsGood: true
IsNotGood: null
IsDefinitelyNotGood: hello
I could use Given that it is a change in behavior and that older versions of .NET would consider types not denoted with |
Code speaks a thousand words :). Thank you for the simple example. We may be limited to what reflection gives us in terms of nullability. I haven’t looked in to how we can determine that, so it’s an unknown if we can even do it, but, I will definitely look in to it. I’m working a couple of other issues at the moment so it’ll be after I finish them. we also gladly accept pull requests, so if you would like to take a stab at it, go for it. |
I could be wrong, but I think this is typically solved in serialization by using the |
@MetaFight |
I’m going to try and get to this in the next few weeks. I’m planning nullable checks and required keywords. As long as they are accessible through the field/property attributes. If they aren’t there’s nothing I can do. |
There's a related problem where non-nullable lists are nulled out if an empty YAML key is given. Instead of the (empty) This may also turn out to be a limitation of what reflection gives you, but I figured I'd add my observation and a small sample program. In the third case, the pre-initialized empty list gets overwritten. #nullable enable
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
var deserializer = new DeserializerBuilder()
.IgnoreUnmatchedProperties()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
{
const string YamlWithListItems = """
strings:
- foo
- bar
""";
var yamlWithListItems = deserializer.Deserialize<MyYaml>(new StringReader(YamlWithListItems));
PrintList(yamlWithListItems.Strings); // foo|bar => OK
}
{
const string YamlWithoutList = """
something: else
""";
var yamlWithoutList = deserializer.Deserialize<MyYaml>(new StringReader(YamlWithoutList));
PrintList(yamlWithoutList.Strings); // (empty) => OK
}
{
const string YamlWithoutListItems = """
strings:
""";
var yamlWithoutListItems = deserializer.Deserialize<MyYaml>(new StringReader(YamlWithoutListItems));
PrintList(yamlWithoutListItems.Strings); // (null) => BAD
}
static void PrintList(List<string>? list)
{
Console.WriteLine(
list switch {
null => "(null)",
[] => "(empty)",
[..] => string.Join("|", list),
}
);
}
class MyYaml
{
public List<string> Strings { get; set; } = [];
} Sample project: https://github.com/mrubli/yamldotnet-null-lists |
Thanks. I’ll add that to the feature. I have code ready for the original feature in this issue. Just need better WiFi to push it up. |
I’ve been thinking about the null list. Technically the spec says that if there’s nothing there then it should be treated as null. So it’s working as designed. Digging into the code it could be pretty complicated and hacky to create the list/enumerator object before it knows what’s in the yaml. For example, strings. That type is an enumerable char. It implements ienumerable and ienumerable. That’s just one example right off the top that complicates creating an object before the yaml specifies if it’s a list/sequence or if it’s a scalar. I’m thinking I’m going to leave this for now since it is following the spec. |
This work is complete now. |
I understand. It's basically the YAML spec vs. the C# spec and something has to give. It was easy enough to work around in code once the problem was known. Perhaps adding a note to the documentation would be helpful but I don't know where the best place for that would be. |
Describe the bug
If the YAML has a value set to
null
, but the object does not declare the type as nullable, YamlDotNet forces it to benull
anyway (reference types) or the default value (value types). This can lead to strange unexpected behavior (especially for value types) since the application has no way of knowing whether the default value was set or if it was set to null. It should throw a YamlException just as it would for any other wrong type (e.g., deserializing "hello" to a boolean).To Reproduce
Define an object with a non-nullable property and deserialize to it with YAML where the property is set to
null
.The text was updated successfully, but these errors were encountered: