如何将派生类型A转换为基类型B以隐藏派生属性?
问题:子类实例转父类后,如何隐藏子类属性避免序列化?
先看简化后的代码:
var a = new A(); var b = (B)a; Console.WriteLine(b); public class A : B { public string Name { get; set; } = "Name"; } public class B { public string Test { get; set; } = "Test"; }
问题是:把A的实例a强制转成B类型后,A的属性依然会被序列化,在Postman调用API时会返回这些子类属性,不符合预期。
我试过手动创建新的B对象:
var b = new B() { Test = a.Test };
这种方法有效,但手动逐个赋值感觉不是最优解。
补充说明
单独调用JsonSerializer.Serialize(b)只会返回B的属性,但.NET Web API的默认序列化逻辑和单独调用不一样,会把A的属性也返回。
另外序列化结果和框架有关:
- Newtonsoft:会序列化A和B的所有属性
- System.Text.Json:仅序列化B的属性
可行解决方案
1. 用映射工具简化对象复制
如果属性多,手动赋值太麻烦,可以用AutoMapper这类工具,只需一次配置就能自动映射:
// 全局配置(只需要配置一次) var config = new MapperConfiguration(cfg => cfg.CreateMap<A, B>()); var mapper = config.CreateMapper(); // 转换 var b = mapper.Map<B>(a);
本质还是创建新对象,但不用手动写每个属性的赋值逻辑,维护起来更方便。
2. 针对Newtonsoft.Json配置序列化规则
如果项目用的是Newtonsoft.Json(早期ASP.NET Core默认框架),可以通过配置让序列化只处理声明的类型:
- 全局配置(在Program.cs/Startup.cs中):
services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.TypeNameHandling = TypeNameHandling.None; options.SerializerSettings.ContractResolver = new DefaultContractResolver { IgnoreSerializableAttribute = true, IgnoreSerializableInterface = true }; });
- 局部处理(单个接口返回时):
return Ok(JsonConvert.SerializeObject(b, typeof(B), new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None }));
3. 确保API返回声明类型为B(System.Text.Json)
如果用的是.NET Core 3.0+默认的System.Text.Json,只要API的返回类型明确声明为B,框架就会自动只序列化B的属性:
[HttpGet] public B GetData() { var a = new A(); B b = a; return b; }
如果返回IActionResult,也要显式转换类型:
return Ok((B)a);
4. 用匿名类型快速筛选属性
如果属性不多,直接用匿名类型提取需要的属性也是个简单办法:
var result = new { Test = a.Test }; return Ok(result);
内容的提问来源于stack exchange,提问作者Fernell85
相关产品推荐
相关产品推荐

