使用System.Text.Json多态序列化时OpenAPI出现重复键错误
解决System.Text.Json多态序列化的重复键与类型信息缺失问题
核心问题根源
你碰到的重复键错误,本质是同一个实现类被多个父接口重复标记[JsonDerivedType],导致System.Text.Json构建类型映射时出现冲突;而拆分配置到子接口后无类型信息,是因为序列化时实际处理的是顶层IObject接口,子接口的派生配置无法被顶层接口的序列化逻辑识别。
正确配置方案
1. 仅在顶层接口统一配置所有派生类型
放弃在IContainer、IChild等子接口上添加[JsonDerivedType],只在最基础的IObject接口上集中配置所有实现类,且每个类仅配置一次:
[JsonDerivedType(typeof(ObjectType1), typeDiscriminator: "ObjectType1")] [JsonDerivedType(typeof(ObjectType2), typeDiscriminator: "ObjectType2")] [JsonDerivedType(typeof(ObjectType3), typeDiscriminator: "ObjectType3")] public interface IObject { int Id {get;set;} }
2. 严格避免跨接口重复标记派生类
像ObjectType3这类实现多个子接口的类,绝对不能在任何子接口上再添加[JsonDerivedType(typeof(ObjectType3))],否则会和IObject上的配置冲突,触发重复键异常。
3. 确保序列化时使用顶层接口类型
在Minimal API的返回值或参数中,明确使用IObject或List<IObject>类型,让System.Text.Json触发顶层接口的派生类型映射,输出类型鉴别符:
app.MapGet("/objects", () => { List<IObject> objects = new() { new ObjectType1 { Id = 1 }, new ObjectType2 { Id = 2, Children = new List<IObject>() }, new ObjectType3 { Id = 3 } }; return Results.Ok(objects); });
4. 修复Swagger 500错误
之前的Swagger报错,是重复派生配置导致Schema生成失败。统一配置后,需在Program.cs中添加Swagger多态支持:
builder.Services.AddSwaggerGen(options => { options.UseOneOfForPolymorphism(); options.SelectSubTypesUsing(baseType => { if (baseType == typeof(IObject)) { return new[] { typeof(ObjectType1), typeof(ObjectType2), typeof(ObjectType3) }; } return Enumerable.Empty<Type>(); }); });
额外注意事项
- 类型鉴别符(
typeDiscriminator)要保证全局唯一,不能重复。 - 如果存在抽象基类(如
DisplayBaseClass),可选择在抽象基类上配置派生类型,但需注意:不要同时在接口和抽象基类上重复配置同一个实现类。 - 反序列化时,确保传入的JSON包含正确的类型鉴别符(默认是
$type字段),System.Text.Json才能正确解析到对应实现类。
内容的提问来源于stack exchange,提问作者Chris K
相关产品推荐
相关产品推荐

