随着 .NET 7.0 的发布,System.Text.Json
应该支持多态代码。不幸的是,当您需要从控制器的方法返回派生类型的实例时,它似乎无法开箱即用。例如,假设以下模型:
public class Base {}
public class Derived1: Base { }
public class Derived2: Base { }
还假设我们有以下动态类型信息解析器:
public class JsonHierarchyTypeInfoResolver : DefaultJsonTypeInfoResolver {
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options) {
var jsonTypeInfo = base.GetTypeInfo(type, options);
if( typeof(Base) == jsonTypeInfo.Type ) {
jsonTypeInfo.PolymorphismOptions = new( ) {
TypeDiscriminatorPropertyName = "$type",
IgnoreUnrecognizedTypeDiscriminators = true,
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
DerivedTypes = {
new JsonDerivedType(typeof(Derived1), typeof(Derived1).AssemblyQualifiedName!),
new JsonDerivedType(typeof(Derived2), typeof(Derived2).AssemblyQualifiedName!)
}
};
}
return jsonTypeInfo;
}
}
然后,通过执行以下操作在应用程序中使用它:
builder.Services.AddControllers( )
.AddJsonOptions(options => {
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.TypeInfoResolver = new JsonHierarchyTypeInfoResolver( );
});
我们还假设我们有一个简单的控制器,它有一个简单的方法,如下所示:
[ApiController]
[Route("[controller]")]
public class DEMOController : ControllerBase {
[HttpGet]
public ActionResult<Base> GetAsync() {
var derived = new Derived1( );
return Ok(derived);
}
}
每当调用该方法时,它都不会像我预期的那样生成带有类型鉴别器的 json。看来问题出在SystemTextJsonOutputFormatter
当它尝试使用以下代码序列化对象时:
await JsonSerializer.SerializeAsync(responseStream, context.Object, objectType, SerializerOptions, httpContext.RequestAborted);
方法如下objectType
已初始化:
// context.ObjectType reflects the declared model type when specified.
// For polymorphic scenarios where the user declares a return type, but returns a derived type,
// we want to serialize all the properties on the derived type. This keeps parity with
// the behavior you get when the user does not declare the return type and with Json.Net at least at the top level.
var objectType = context.Object?.GetType() ?? context.ObjectType ?? typeof(object);
由于该方法使用派生类型,因此自定义信息类型解析器将无法发挥其魔力。我错过了什么吗?这是一个已知的问题?这是否意味着我应该继续使用 json.net 而不是尝试迁移到 System.Text.Json?