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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 05:52:36