Skip to content
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

ObjectNodeDeserializer: Naming Convention Error on Deserialization #915

Open
BlankDev117 opened this issue Mar 18, 2024 · 2 comments
Open

Comments

@BlankDev117
Copy link

BlankDev117 commented Mar 18, 2024

Describe the bug
Deserializing an object, using PascalCase naming convention, appears to break YamlDotNet if the serialization process was not already in PascalCase, i.e. serialized with CamelCase or UnderScored naming conventions.

To Reproduce

  1. Set a naming convention for serialization other than PascalCase
  2. Serialize data with this naming convention.
  3. Attempt to deserialize this data, using the deserialization naming convention, with PascalCase
  4. See an error regarding the {LOWER_CASE PROPERTY_NAME} not matching any of the property names on the main object.

image
[Test Data for serialization]

image
[Serialization Settings. Notice the differences in the naming convetions]

image
[Output of the above serialization to a local file. Notice the today property listed on the yaml file on line 1]

The resulting error:

  Message: 
    YamlDotNet.Core.YamlException : Property 'today' not found on type 'Discriminators.UnitTests.Helpers.TestChildA'.

  Stack Trace: 
    ObjectNodeDeserializer.Deserialize(IParser parser, Type expectedType, Func`3 nestedObjectDeserializer, Object& value)
    TypeDiscriminatingNodeDeserializer.Deserialize(IParser reader, Type expectedType, Func`3 nestedObjectDeserializer, Object& value)
    NodeValueDeserializer.DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer)
    AliasValueDeserializer.DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer)
    <>c__DisplayClass5_0.<DeserializeValue>b__0(IParser r, Type t)
    CollectionNodeDeserializer.DeserializeHelper(Type tItem, IParser parser, Func`3 nestedObjectDeserializer, IList result, Boolean canUpdate, INamingConvention enumNamingConvention)
    ArrayNodeDeserializer.Deserialize(IParser parser, Type expectedType, Func`3 nestedObjectDeserializer, Object& value)
    NodeValueDeserializer.DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer)
    AliasValueDeserializer.DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer)
    Deserializer.Deserialize(IParser parser, Type type)
    Deserializer.Deserialize(TextReader input, Type type)
    YamlSerializer.DeserializeAsync(Byte[] data, Type type, CancellationToken cancellationToken) line 57
    PolymorphismYamlTypeDiscriminatorTests.Validate_ServiceCollectionExtensions() line 95
    <>c.<ThrowAsync>b__128_0(Object state)

Expected Result
Deserialization of the input file or data stream should find the expected property name when using PascalCase

Notes
From what I can tell, the issue arises in the ObjectNodeDeserializer, here. Problem appears to be a direct usage of the property name, rather than applying the NamingConvention for the Deserialization naming convention. In fact, this class does not reference the deserialization naming convention at all and instead only uses an enum naming convention.

The current workaround seems to simply use PascalCase for both the serialization and deserialization processes, unless I'm horribly wrong about what I'm seeing and it being some kind of other configuration, or user, issue.

@skrysmanski
Copy link

I also ran into this but with CamelCaseNamingConvention (I didn't know it was different than PascalCase).

I have a class like this:

namespace WishListApp.DataModels;

public sealed class WishListAppSettings
{
    public string? LastOpenedFile { get; set; }
}

And with this YAML:

LastOpenedFile: C:\Users\...

I was getting this exception:

Property 'LastOpenedFile' not found on type 'WishListApp.DataModels.WishListAppSettings'.

Which is quite confusing because it's obviously wrong. The problem here is that YAML.NET also uses the name from the file for the exception message but it should use the name after applying the naming convention to avoid confusion for developers like me.

I also think that the deserialization sample is wrong by using CamelCaseNamingConvention - it should use PascalCaseNamingConvention.

@EdwardCooke
Copy link
Collaborator

Using the naming convention when deserializing is sketchy at best. There's not much of a way to guarantee what the resulting property casing or name should really actually be. They work fantastic for serializing though. My recommendation would be to use the yamlmember attribute and specify what the name should actually be in the yaml file, that's the only way to guarantee what should be what when different than the property/field name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants