You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

System.Text.Json反序列化报固定大小集合异常是使用错误还是Bug

核心结论

你遇到的不是历史已关闭bug的复现,也不是使用方式错误,本质是System.Text.Json和Newtonsoft.Json对集合属性反序列化的默认实现逻辑存在差异。

原因说明

两个库的集合反序列化逻辑区别如下:

  • Newtonsoft.Json反序列化集合属性时,会先完整构造出反序列化后的集合对象,再调用属性的set方法完成赋值,全程不会调用属性getter取现有集合做修改。你的ClassB中ArrayOfString的set逻辑只要接收到长度为1的字符串数组,就会把值同步给基类的SingularString属性,因此可以正常运行。
  • System.Text.Json对可写集合属性默认采用填充现有集合的逻辑:它会先调用属性getter拿到已存在的集合实例,再把JSON中解析出的元素逐个添加到这个集合中,默认不会在解析完所有元素后调用属性set方法。
    你的ArrayOfString属性getter每次返回的是长度固定为1的新字符串数组,数组本身是固定长度结构,不支持Add/Insert等会修改集合长度的操作,因此System.Text.Json尝试往里面添加元素时,直接抛出「Collection was of a fixed size」异常,你写的set逻辑根本不会被执行。
解决方法

两种方案可按需选择,优先推荐第一种,改动成本最低:

  1. 修改System.Text.Json的对象创建处理配置,强制它对集合采用替换逻辑,和Newtonsoft.Json行为对齐:反序列化时生成新的集合实例后调用属性set赋值,不会再调用getter取现有集合填充。
    全局配置示例:
    var jsonOptions = new JsonSerializerOptions
    {
        PreferredObjectCreationHandling = JsonObjectCreationHandling.Replace
    };
    ClassB classB = System.Text.Json.JsonSerializer.Deserialize<ClassB>(json, jsonOptions);
    
    单属性配置(.NET 7及以上版本支持,不需要改全局配置):
    class ClassB : BaseClass
    {
        [System.Text.Json.Serialization.JsonObjectCreationHandling(JsonObjectCreationHandling.Replace)]
        public string[] ArrayOfString
        {
            get => new string[] { base.SingularString };
            set
            {
                if((value != null) && (value.Length == 1))
                {
                    base.SingularString = value[0];
                }
            }
        }
    }
    
    class BaseClass
    {
        public string SingularString { get; set; } = "Hello World";
    }
    
  2. 调整属性实现逻辑,不要让getter返回固定大小的数组,这种方案改动成本更高,更适合属性本身确实需要持有集合实例的场景,你当前同步单值到基类的场景不需要用这种方式。

内容的提问来源于stack exchange,提问作者IV.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:30:47