-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
JsonConverter inconsistency when deserializing into property without public getter #56212
Comments
Tagging subscribers to this area: @eiriktsarpalis, @layomia Issue DetailsDescriptionWith given code public class PrivateGetter<T>
{
public T Property { private get; set; }
public override string ToString()
{
return Property is null ? "null" : Property.ToString();
}
}
public class PublicGetter<T>
{
public T Property { get; set; }
public override string ToString()
{
return Property is null ? "null" : Property.ToString();
}
} var jsonListOfInts = @"
{
""Property"": [ 1 ]
}
";
var jsonInt = @"
{
""Property"": 1
}
";
Console.WriteLine(JsonSerializer.Deserialize<PrivateGetter<List<int>>>(jsonListOfInts));
Console.WriteLine(JsonSerializer.Deserialize<PublicGetter<List<int>>>(jsonListOfInts));
Console.WriteLine(JsonSerializer.Deserialize<PrivateGetter<int>>(jsonInt));
Console.WriteLine(JsonSerializer.Deserialize<PublicGetter<int>>(jsonInt)); Output:
When deserializing a JSON with a Unfortunatelly the documentation site https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-immutability does not specify whether the behaviour is to allow deserializing into property without public getter or not, therefore it is hard to guess whether the case with Configuration.NET Core 3.1 Regression?Other information
|
I can reproduce -- the issue is certainly surprising although I was able to force deserialization for the List case by attaching a That being said, the private getter/public setter combination is unusual, and we generally recommend against using it. We should still fix this and ensure relevant test coverage is added for that particular combination. |
Doing a bit more digging -- the root cause appears to be this method which seems to applying different logic depending on whether the property type is a collection or not. Not sure why though, I couldn't find any comments justifying the split. @layomia is this by design? should we be making the change to support setter-only deserialization? |
We seem to have a test that validates the behavior as reported: runtime/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs Lines 1003 to 1013 in ec2d25c
and for value types: runtime/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.NonPublicAccessors.cs Lines 25 to 26 in ec2d25c
Again, I don't have context as to why we're doing this, but likely we're closing this as by-design behavior. |
Understood, thanks anyway. |
After private discussion with @layomia we have concluded that we should change the That being said, it is a fix that probably doesn't meet the bug bar for RC1 since a) it affects a relatively rare corner case and b) it can be easily worked around by adding a |
Just documenting a real-life use case here to make sure this makes it into I'm using a write-only property for refactoring purposes such as property renames and the like, where the object is persisted as json. [Obsolete("Don't use this, only for data-migration purposes.")]
public List<EnvironmentHistoryItem> EnvironmentHistory
{
set => EnvironmentHistoryV2 = new EnvironmentHistory { Items = value };
}
public EnvironmentHistory EnvironmentHistoryV2 { get; set; } = new EnvironmentHistory(); I didn't expect this bug, took me a couple of hours to find it (and this github issue), and Newtonsoft also deserializes this correctly. The |
We won't have time to work on this for .NET 7, moving to Future. |
FWIW we passed an opportunity to fix this behavior when refactoring for .NET 7 work. Even though the current behavior is inconsistent, we felt it would be too much of breaking change to justify fixing. We might revisit in the future assuming there is demand. |
Description
With given code
Output:
When deserializing a JSON with a
List<>
property with a non-public getter, the value is not deserialized and property isnull
.However when serializing and
int
the same way, a value of1
is (correctly) assigned.I expect that the behaviour of deserializing into property with non-public getter is independent of the property type.
Unfortunatelly the documentation site https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-immutability does not specify whether the behaviour is to allow deserializing into property without public getter or not, therefore it is hard to guess whether the case with
int
is wrong or theList<>
one.Configuration
.NET Core 3.1
Regression?
Other information
The text was updated successfully, but these errors were encountered: