ASP.NET Core6WebAPI和C#。我想要一个具有多态类型集合的REST端点:
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);如果调用该方法,则返回:
{ "data": [ {"a": 20} ] }好像数组元素是根据数组的声明类型序列化的,而不是运行时类型。
用List<Base>试过,结果一样。
能绕开吗,拜托?如果返回类型本身是多态的,则Web序列化逻辑会考虑这一点。
编辑:一个简单的解决方法是将Foo.data声明为object[]。但这将扼杀Swagger类型的注释--在我的例子中是不可接受的。
编辑:通过在Web上提供[ProducesResponseType(typeof(RealFoo), 200)]注释来欺骗Swagger。
发布于 2022-10-18 16:02:46
如果您启用Swagger中的多态性,它将工作。
builder.Services.AddSwaggerGen(c => c.UseOneOfForPolymorphism());并创建一个自定义转换器。请注意,这实际上是一个基于您的模型的工作示例。
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();
}
}寄存器转换器
builder.Services.Configure<JsonOptions>(options =>
{
options.SerializerOptions.Converters.Add(new CustomConverter());
});更多信息,在这里如何在.NET中为JSON序列化(编组)编写自定义转换器
还考虑了对Newtonsoft.Json的评论
发布于 2022-10-18 16:14:13
我听到其他人在说什么,但去我想要的地方的最起码的方法是:
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都有一个。
https://stackoverflow.com/questions/74113460
复制相似问题