首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WebAPI中集合中的多态类型

WebAPI中集合中的多态类型
EN

Stack Overflow用户
提问于 2022-10-18 15:17:12
回答 2查看 57关注 0票数 -1

ASP.NET Core6WebAPI和C#。我想要一个具有多态类型集合的REST端点:

代码语言:javascript
复制
app.MapGet("/api/temp", Temp);

//...
static Foo Temp()
{
    return new Foo(new Base[] { new Derived(10, 20) });
}

public abstract record Base(int a);
public record Derived(int b, int a): Base(a);
public record Foo(Base[] data);

如果调用该方法,则返回:

代码语言:javascript
复制
{ "data": [ {"a": 20} ] }

好像数组元素是根据数组的声明类型序列化的,而不是运行时类型。

List<Base>试过,结果一样。

能绕开吗,拜托?如果返回类型本身是多态的,则Web序列化逻辑会考虑这一点。

编辑:一个简单的解决方法是将Foo.data声明为object[]。但这将扼杀Swagger类型的注释--在我的例子中是不可接受的。

编辑:通过在Web上提供[ProducesResponseType(typeof(RealFoo), 200)]注释来欺骗Swagger。

EN

回答 2

Stack Overflow用户

发布于 2022-10-18 16:02:46

如果您启用Swagger中的多态性,它将工作。

代码语言:javascript
复制
builder.Services.AddSwaggerGen(c => c.UseOneOfForPolymorphism());

并创建一个自定义转换器。请注意,这实际上是一个基于您的模型的工作示例。

代码语言:javascript
复制
public class CustomConverter : JsonConverter<Base>
{
    public override Base Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // omitted ...
        throw new JsonException();
    }

    public override void Write(Utf8JsonWriter writer, Base baseModel, JsonSerializerOptions options)
    {
        writer.WriteStartObject();

        if (baseModel is Derived derived)
        {
            writer.WriteNumber("a", derived.a);
            writer.WriteNumber("b", derived.b);
        }

        writer.WriteEndObject();
    }
}

寄存器转换器

代码语言:javascript
复制
builder.Services.Configure<JsonOptions>(options =>
{
    options.SerializerOptions.Converters.Add(new CustomConverter());
});

更多信息,在这里如何在.NET中为JSON序列化(编组)编写自定义转换器

还考虑了对Newtonsoft.Json的评论

票数 1
EN

Stack Overflow用户

发布于 2022-10-18 16:14:13

我听到其他人在说什么,但去我想要的地方的最起码的方法是:

代码语言:javascript
复制
app.MapGet("/api/temp", Temp);

//...
[ProducesResponseType(typeof(Foo), 200)]
static OFoo Temp()
{
    return new OFoo(new Base[] { new Derived(10, 20) });
}

public abstract record Base(int a);
public record Derived(int b, int a): Base(a);
public record Foo(Base[] data);
public record OFoo(object[] data);

值得注意的是,这种方法被隔离到存在多态元素集合的方法中,所需的键入量相对于所需的Base子类型的数量是O(1),通常不依赖于集合元素类型树的复杂性。在我的实际项目中,它比Base/Derived要复杂得多,每个int都有一个。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74113460

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档