-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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 does not fill JsonExtensionData when a property with the same name already exists or has the JsonIgnoreAttribute #68895
Comments
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis Issue DetailsDescriptionThe JsonExtensionData property does not contain the properties from the deserialized Json that have matching read only or JsonIgnore properties on the target object. Reproduction StepsWhen deserializing that json: var json = @"{ ""value"": { ""content"": ""test"" } }"; into that object public class TestDefault
{
[JsonIgnore]
public JsonElement Value => Values["value"];
[JsonExtensionData]
public Dictionary<string, JsonElement> Values { get; set; }
} with this code: [TestClass]
public class TestNotionHtml
{
[TestMethod]
public void TestJsonExtensionData_Inherited()
{
var json = @"{ ""value"": { ""content"": ""test"" } }";
var r = JsonSerializer.Deserialize<TestDefault>(json, new(JsonSerializerDefaults.Web));
Assert.IsNotNull(r);
Assert.IsNotNull(r.Values);
Assert.AreEqual(1, r.Values.Count);
Assert.IsTrue(r.Values.ContainsKey("value"));
Assert.IsNotNull(r.Value);
}
} the Values dictionary is empty. Expected behaviorValues should contains all properties that are not deserialized Actual behaviorValues is empty Regression?No Known WorkaroundsNone Configuration.net6 system.text.json 6.0.3 Other informationNo response
|
I can reproduce, here's a minimal reproduction: var json = @"{ ""Value"": true }";
var r = JsonSerializer.Deserialize<TestDefault>(json);
Console.WriteLine(r.ExtensionData?.Count ?? 0); // prints 0
public class TestDefault
{
public bool Value { get; }
[JsonExtensionData]
public Dictionary<string, object> ExtensionData { get; set; }
} I wouldn't necessarily consider this to be a bug, although I can see why the expected behavior would be nice to have. We might want to consider it in a future release. cc @layomia @steveharter |
This shouldn't have been closed, right? |
If someone still needs to use this approach, the issue can be avoided by adding JsonPropertyName attribute that doesn't match to any property of your object. public class TestDefault
{
[JsonPropertyName($"${nameof(Value)}"), JsonIgnore]
public JsonElement Value => Values["value"];
[JsonExtensionData]
public Dictionary<string, JsonElement> Values { get; set; }
} |
Better workaround would be: using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
JsonSerializerOptions options = new()
{
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
{
Modifiers =
{
ti =>
{
if (ti.Kind == JsonTypeInfoKind.Object)
{
JsonPropertyInfo[] props = ti.Properties
.Where(prop => prop.AttributeProvider == null || prop.AttributeProvider.GetCustomAttributes(typeof(JsonIgnoreAttribute), false).Length == 0)
.ToArray();
if (props.Length != ti.Properties.Count)
{
ti.Properties.Clear();
foreach (var prop in props)
{
ti.Properties.Add(prop);
}
}
}
}
}
}
};
var json = @"{ ""Value"": { ""content"": ""test"" } }";
TestDefault obj = JsonSerializer.Deserialize<TestDefault>(json, options);
if (obj.Values != null)
{
foreach (var (k, v) in obj.Values)
{
Console.WriteLine($"{k} => {v}"); // Value => { "content": "test" }
}
}
public class TestDefault
{
[JsonIgnore]
public JsonElement Value => Values["value"];
[JsonExtensionData]
public Dictionary<string, JsonElement>? Values { get; set; }
} Note 1: ignored properties will also not work with parametrized constructors in that case (assuming that was desired in the first place). Note 2: It needs testing with inheritance if needed for production |
Description
The JsonExtensionData property does not contain the properties from the deserialized Json that have matching read only or JsonIgnore properties on the target object.
Reproduction Steps
When deserializing that json:
into that object
with this code:
the Values dictionary is empty.
Expected behavior
Values should contains all properties that are not deserialized
Actual behavior
Values is empty
Regression?
No
Known Workarounds
None
Configuration
.net6
system.text.json 6.0.3
Other information
No response
The text was updated successfully, but these errors were encountered: