System.Text.Json源生成器:JsonSerializerContext需指定哪些类型?
System.Text.Json源生成器:JsonSerializerContext类型指定规则与优化
场景与问题
现有Dto类型:
public class OrderDto { ... public List<OrderLineDto> Lines { get; set; } } public class OrderLineDto { ... }
存在以下反序列化场景:
JsonSerializer.DeserializeAsync<List<OrderDto>>(...); JsonSerializer.DeserializeAsync<OrderDto>(...); JsonSerializer.DeserializeAsync<List<OrderLineDto>>(...); JsonSerializer.DeserializeAsync<OrderLineDto>(...);
疑问点:
- 仅添加
[JsonSerializable(typeof(OrderDto))]是否足够?还是需要为每个反序列化的根类型单独添加属性? - 文档提到“集合类型需配合[JsonSerializable]”,但又说“成员类型无需显式指定”,那
List<OrderLineDto>作为OrderDto的成员,同时又被用作根类型反序列化,是否需要单独标记? - 当前项目需标记约250个类型,生成1650个源文件,编译缓慢、库体积翻倍,如何优化?
核心规则说明
1. 根类型必须显式标记
所有直接作为JsonSerializer.Serialize/Deserialize泛型参数的类型(即“根类型”),必须通过[JsonSerializable]显式标记在JsonSerializerContext上。源生成器只会为显式标记的根类型生成完整的序列化/反序列化逻辑。
2. 嵌套成员类型无需单独标记
如果某个类型仅作为已标记根类型的嵌套成员存在(比如OrderLineDto是OrderDto.Lines的元素类型),则不需要单独标记该成员类型——源生成器会自动递归处理这些嵌套类型的序列化逻辑。但如果该类型本身也被用作根类型(比如直接反序列化OrderLineDto),则必须显式标记。
针对场景的具体结论
- 仅添加
[JsonSerializable(typeof(OrderDto))]不够。因为你还有直接反序列化List<OrderDto>、OrderLineDto、List<OrderLineDto>的场景,这些都是根类型,必须单独添加标记:[JsonSerializable(typeof(OrderDto))] [JsonSerializable(typeof(List<OrderDto>))] [JsonSerializable(typeof(OrderLineDto))] [JsonSerializable(typeof(List<OrderLineDto>))] public partial class MyJsonContext : JsonSerializerContext { } - 关于文档冲突:文档中“集合类型需配合[JsonSerializable]”是针对集合作为根类型的情况;“成员类型无需显式指定”是针对类型仅作为嵌套成员的情况。
List<OrderLineDto>作为OrderDto的成员时不需要标记,但它被直接用作根类型反序列化时,必须单独标记。
编译优化建议
- 避免冗余标记:如果一个类型既作为根类型,又作为其他类型的成员,只需要标记一次根类型即可,嵌套成员的类型会被自动处理。
- 拆分上下文:将类型按业务模块拆分到多个
JsonSerializerContext中(比如订单模块、用户模块各一个上下文),减少单个上下文生成的源文件数量,提升编译速度。 - 调整反序列化逻辑:如果某些集合根类型的反序列化可以通过父类型间接获取(比如先反序列化包含
List<OrderLineDto>的父Dto,再提取集合),则可以移除该集合类型的标记,减少需要标记的类型数量。 - 使用
JsonDerivedType处理多态:如果存在继承关系的类型,通过[JsonDerivedType]标记派生类型,避免为每个派生类型单独添加[JsonSerializable]。
内容的提问来源于stack exchange,提问作者adrianm
相关产品推荐
相关产品推荐

