ASP.NET Core 2.0返回IActionResult时控制SerializerSettings的问题
在ASP.NET Core 2.0中为抽象基类序列化添加具体类型标识
嗨,我来帮你搞定这个问题!在ASP.NET Core 2.0 WebAPI里,要让抽象基类Trade的JSON序列化结果包含具体类型的标识,我们可以通过配置**Newtonsoft.Json(Json.NET)**的序列化规则来实现——毕竟ASP.NET Core 2.0默认就是用Json.NET处理JSON序列化的。
下面是具体的实现步骤:
1. 标记抽象基类的子类
首先,你需要告诉Json.NET哪些类型是Trade的具体子类。最直接的方式是在抽象基类上添加[JsonDerivedType]特性:
using Newtonsoft.Json; [JsonDerivedType(typeof(StockTrade), typeName: "StockTrade")] [JsonDerivedType(typeof(ForeignExchangeTrade), typeName: "ForeignExchangeTrade")] public abstract class Trade { public int Id { get; set; } // 其他公共属性 } // 示例具体子类 public class StockTrade : Trade { public string StockSymbol { get; set; } public int Quantity { get; set; } } public class ForeignExchangeTrade : Trade { public string CurrencyPair { get; set; } public decimal Amount { get; set; } }
这里的typeName参数会作为类型标识出现在最终的JSON里,方便反序列化时识别具体类型。
2. 全局配置Json.NET的序列化设置
接下来,在Startup.cs的ConfigureServices方法中,配置Json.NET开启类型名称处理:
public void ConfigureServices(IServiceCollection services) { services.AddMvc() .AddJsonOptions(options => { // 自动为多态类型添加类型标识字段(默认字段名为$type) options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto; // 可选:自定义类型标识的格式,比如只保留类型名不包含程序集信息 options.SerializerSettings.TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; }); }
TypeNameHandling.Auto:只会在序列化多态类型(比如抽象基类的实例)时自动添加$type字段,避免不必要的冗余。- 如果需要强制所有对象都添加类型标识,可以改用
TypeNameHandling.Objects或TypeNameHandling.All。
3. 验证序列化结果
现在当你的Get方法返回具体的Trade子类实例时,序列化后的JSON会包含类型标识,比如:
{ "$type": "YourApp.Models.StockTrade", "Id": 5, "StockSymbol": "AAPL", "Quantity": 100 }
4. 安全提示(重要)
使用TypeNameHandling时要注意反序列化安全问题——如果你的API接受来自不可信来源的JSON,恶意攻击者可能通过构造特定的$type字段来触发危险类型的反序列化。
为了避免这个风险,建议自定义SerializationBinder来限制允许反序列化的类型:
options.SerializerSettings.SerializationBinder = new TradeTypeBinder(); public class TradeTypeBinder : ISerializationBinder { private readonly HashSet<Type> _allowedTypes = new HashSet<Type> { typeof(StockTrade), typeof(ForeignExchangeTrade) }; public Type BindToType(string assemblyName, string typeName) { // 查找允许的类型,找不到则抛出异常 var allowedType = _allowedTypes.FirstOrDefault(t => t.FullName == typeName); if (allowedType == null) { throw new ArgumentException($"不允许反序列化类型:{typeName}"); } return allowedType; } public void BindToName(Type serializedType, out string assemblyName, out string typeName) { assemblyName = null; // 不输出程序集名称 typeName = serializedType.FullName; } }
这样就能确保只有你指定的Trade子类可以被反序列化,提升API的安全性。
内容的提问来源于stack exchange,提问作者David Waterworth
相关产品推荐
相关产品推荐

