最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Why can't I deserialize JSON to an object with a List<T> property - Stack Overflow

programmeradmin3浏览0评论

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
  • Are you simply using .NET 8, or did you experience success using older versions of .NET, and just ran into the issue once you updated to .NET 8? If the latter, which version were you using before where it worked? – TylerH Commented Mar 17 at 18:50
  • why is Children a get only property? – Rand Random Commented Mar 17 at 18:54
  • 1 since Child has no public empty constructor I would expect issues deserializing this class – Rand Random Commented Mar 17 at 18:56
  • I just put the .NET version to be specific in case there are differences in previous or later versions. I made Children "get only" per my usual style of doing so for list properties that generally never need to get set. I just initialize them with an empty list and other code can add/remove items as needed and we never need to worry about a null reference exception accessing that property. I thought this was a best practice... and in fact if I don't make it read only, I get a linting message in Visual Studio: "CA2227: Collection properties should be read only." – Kairei Commented Mar 17 at 19:06
  • 1 FYI - learn.microsoft/en-us/dotnet/standard/serialization/… – Rand Random Commented Mar 17 at 19:18
 |  Show 4 more comments

1 Answer 1

Reset to default 5

This 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>();
}
发布评论

评论列表(0)

  1. 暂无评论