With .NET 8, using System.Text.Json
, I can serialize/deserialize a List<T>
. I can also serialize an object with a property of type List<T>
. However, I cannot deserialize that object. Here is a test that demonstrates the issue:
using System.Text.Json;
namespace JsonDeserializationTests
{
public class Parent
{
public List<Child> Children { get; } = new List<Child>();
}
public class Child
{
public Child(string name)
{
Name = name;
}
public string Name { get; set; }
}
public class JsonSerializationTestSimple
{
[Fact]
public void CanSerializeAndDeserialize()
{
var parent = new Parent();
parent.Children.Add(new Child("Child A"));
parent.Children.Add(new Child("Child B"));
// Serialize a List<Child> instance directly.
var childrenJson = JsonSerializer.Serialize(parent.Children);
var deserializedChildren = JsonSerializer.Deserialize<List<Child>>(childrenJson);
var childrenJson2 = JsonSerializer.Serialize(deserializedChildren);
Assert.True(childrenJson == childrenJson2); // This succeeds
// Both have the same JSON:
// [{"Name":"Child A"},{"Name":"Child B"}]
// Now try to serialzie the entire Parent object that has a List<Child> property.
var parentJson = JsonSerializer.Serialize(parent);
var deserializedParent = JsonSerializer.Deserialize<Parent>(parentJson);
var parentJson2 = JsonSerializer.Serialize(deserializedParent);
Assert.True(parentJson == parentJson2); // This fails
// parentJson is as expected:
// {"Children":[{"Name":"Child A"},{"Name":"Child B"}]}
// but parentJson2 shows we did not deserialize the Children property:
// {"Children":[]}
}
}
}
With .NET 8, using System.Text.Json
, I can serialize/deserialize a List<T>
. I can also serialize an object with a property of type List<T>
. However, I cannot deserialize that object. Here is a test that demonstrates the issue:
using System.Text.Json;
namespace JsonDeserializationTests
{
public class Parent
{
public List<Child> Children { get; } = new List<Child>();
}
public class Child
{
public Child(string name)
{
Name = name;
}
public string Name { get; set; }
}
public class JsonSerializationTestSimple
{
[Fact]
public void CanSerializeAndDeserialize()
{
var parent = new Parent();
parent.Children.Add(new Child("Child A"));
parent.Children.Add(new Child("Child B"));
// Serialize a List<Child> instance directly.
var childrenJson = JsonSerializer.Serialize(parent.Children);
var deserializedChildren = JsonSerializer.Deserialize<List<Child>>(childrenJson);
var childrenJson2 = JsonSerializer.Serialize(deserializedChildren);
Assert.True(childrenJson == childrenJson2); // This succeeds
// Both have the same JSON:
// [{"Name":"Child A"},{"Name":"Child B"}]
// Now try to serialzie the entire Parent object that has a List<Child> property.
var parentJson = JsonSerializer.Serialize(parent);
var deserializedParent = JsonSerializer.Deserialize<Parent>(parentJson);
var parentJson2 = JsonSerializer.Serialize(deserializedParent);
Assert.True(parentJson == parentJson2); // This fails
// parentJson is as expected:
// {"Children":[{"Name":"Child A"},{"Name":"Child B"}]}
// but parentJson2 shows we did not deserialize the Children property:
// {"Children":[]}
}
}
}
Share
Improve this question
edited Mar 20 at 1:00
Zhi Lv
22k1 gold badge27 silver badges37 bronze badges
asked Mar 17 at 18:47
KaireiKairei
1216 bronze badges
9
|
Show 4 more comments
1 Answer
Reset to default 5This is happening because your property Children
does not have a setter, thus is read-only. If you add a setter it will work:
public class Parent
{
public List<Child> Children { get; set; } = new List<Child>();
}
If you want to avoid a public setter, you can also add a private setter and the [JsonInclude]
attribute and it will deserialize correctly:
public class Parent
{
[JsonInclude]
public List<Child> Children { get; private set; } = new List<Child>();
}
Or, as @Rand Random pointed out in the comments, starting in .NET 8 you can deserialize read-only properties by utilizing the JsonObjectCreationHandling
attribute:
public class Parent
{
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
public List<Child> Children { get; } = new List<Child>();
}
Children
a get only property? – Rand Random Commented Mar 17 at 18:54Child
has no public empty constructor I would expect issues deserializing this class – Rand Random Commented Mar 17 at 18:56