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

System.Text.Json: JsonExtensionData deserialization silently fails for a get-only, preallocated dictionary property. #32197

Closed
dbc2 opened this issue Feb 12, 2020 · 1 comment
Assignees
Milestone

Comments

@dbc2
Copy link

dbc2 commented Feb 12, 2020

If I have a get-only, preallocated [JsonExtensionData] property on my model, then the dictionary will be serialized successfully, but will silently fail to be populated on deserialization. This seems wrong. Details as follows.

Say I have the following model:

public class Model
{
    [JsonExtensionData]
    public Dictionary<string, object> ExtensionData { get; } = new Dictionary<string, object>();
}

And the following test method:

public class TestClass
{
    [TestMethod]
    public void TestReadOnlyExtensionDataProperty()
    {
        var model1 = new Model { ExtensionData = { { "item", "item value" } } };

        var json = JsonSerializer.Serialize(model1);

        Debug.WriteLine(json); // Prints {"item":"item value"} as expected

        Assert.AreEqual(json, "{\"item\":\"item value\"}"); // Passes.

        var model2 = JsonSerializer.Deserialize<Model>(json);

        Assert.AreEqual(model1.ExtensionData.Count, model2.ExtensionData.Count, "model2.ExtensionData.Count"); // FAILS!
    }
}

Then the first assert will succeed, because model1 is correctly serialized as {"item":"item value"}. However, the second assert fails, because model2.ExtensionData is empty when deserialized.

Demo fiddle 1 here reproducing the problem.

Conversely, Json.NET is able to round-trip this model successfully, see demo fiddle 2 here.

And if I modify Model.ExtensionData to have a setter that throws an exception, then deserialization also succeeds:

public class Model
{
    readonly Dictionary<string, object> extensionData = new Dictionary<string, object>();

    [JsonExtensionData]
    public Dictionary<string, object> ExtensionData { get => extensionData; set => throw new NotImplementedException(); }
}

Demo fiddle 3 here, which passes.

This seems wrong. Since the dictionary is preallocated it should be populated successfully during deserialization even without a setter -- especially since the setter isn't actually called.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Feb 12, 2020
@layomia layomia removed the untriaged New issue has not been triaged by the area owner label Feb 21, 2020
@layomia layomia self-assigned this Feb 21, 2020
@layomia layomia added this to the 5.0 milestone Feb 21, 2020
@layomia
Copy link
Contributor

layomia commented Mar 26, 2020

This is a duplicate of #30258. For now, like any other property, the extension data property needs a setter to be deserialized into.

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

No branches or pull requests

3 participants