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

System.Text.Json无法反序列化带私有getter的IEnumerable属性的原因分析

System.Text.Json无法反序列化带私有getter的IEnumerable属性的原因分析

这个问题我之前踩过同款坑,其实是System.Text.Json对集合类型和非集合类型的反序列化逻辑差异导致的,我给你掰扯清楚:

首先先明确你的属性定义细节:你写的public BusinessEventType EventType { private get; set; } 其实是「属性本身是public,getter是private,setter是public」(C#里如果属性访问器没写修饰符,默认和属性的访问级别一致)。所以EventType、EventDate、People这三个属性的setter都是public,差异只在getter的权限,但前两个能正常赋值,唯独People不行——核心原因就在于People是集合类型(IEnumerable),而另外两个是非集合类型。

1. 非集合类型的反序列化逻辑(为什么EventType、EventDate正常)

对于值类型(比如DateTime)或者自定义的非集合引用类型(比如你的BusinessEventType),System.Text.Json的反序列化逻辑很直接:只要属性的setter是public,不管getter的权限,它都会直接调用setter把反序列化后的对象/值硬塞给属性。

所以你的EventType和EventDate虽然getter是private,但setter是public,序列化器完全可以绕开getter,直接通过setter赋值,自然能正常工作。

2. 集合类型的反序列化逻辑(为什么People会null)

而集合类型(包括IEnumerable、List、数组这些)的反序列化逻辑就不一样了:
System.Text.Json不会直接调用setter把整个集合对象丢给属性,而是会先尝试通过getter获取当前属性的集合实例:

  • 如果能拿到实例(而且这个实例是可修改的集合,比如List),就直接往里面加反序列化出来的元素;
  • 如果getter访问不了(比如你这里是private get),或者当前实例是null,就算序列化器创建了新的集合实例(比如给IEnumerable默认创建List),也没法完成后续操作——因为它需要通过getter确认集合的状态,private getter直接把路堵死了,最后只能跳过这个属性,让它保持为null。

这就是为什么你把People的getter改成public后就正常了:序列化器能通过getter访问属性,顺利完成集合的创建、填充,再通过public setter把最终的集合实例赋值好。

不想暴露getter的解决办法

如果你不想把People的getter改成public,有两个简单的方案:

  • 方案一:加[JsonInclude]特性:这个特性会告诉System.Text.Json允许访问private的getter/setter,这样即使getter是private,序列化器也能正常处理集合反序列化:
    [JsonInclude]
    public IEnumerable<Person> People { private get; set; }
    
  • 方案二:用具体集合类型并初始化:把People的类型改成List这类具体的可修改集合,再初始化它,配合[JsonInclude]就能正常工作,还能避免null:
    [JsonInclude]
    public List<Person> People { private get; set; } = new List<Person>();
    

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 07:39:53