C#控制台客户端传对象至WebApi端点无法反序列化问题求助
问题根因
反序列化后所有成员为默认值的核心问题有两个:
- 你定义的
Product类成员全是公共字段,没有实现带get/set访问器的公共属性。ASP.NET Core 默认使用的System.Text.Json序列化器,在默认配置下只会序列化/反序列化公共属性,不会处理公共字段,因此无论请求参数是否正确,反序列化时都不会给这些字段赋值,最终只能得到类型默认值。 - 第一种实现方案存在逻辑错误:
PutAsJsonAsync方法本身就会对传入的参数执行JSON序列化,你提前把对象序列化为JSON字符串再传入,会导致字符串被二次序列化(特殊字符被转义、外层多包裹一层引号),服务端拿到的实际是嵌套转义的非法JSON结构,即使字段定义正确也无法正常反序列化。
修复步骤
- 第一步:同步修改客户端、服务端的
Product类定义,把公共字段改为公共属性,修改后代码如下:
public class Product { public string ProductName { get; set; } = string.Empty; public int ProductId { get; set; } = 0; public List<string> ProductInfo { get; set; } = new List<string>(); }
注意:两端的
Product类字段名、字段类型必须完全一致,否则会出现字段匹配失败、部分值丢失的问题。
- 第二步:客户端直接传强类型对象调用接口即可,不需要手动执行序列化操作,参考代码如下:
// 省略HttpClient初始化逻辑 Product p = BuildProductObject(); // 直接传入Product对象,不要传手动序列化后的字符串 HttpResponseMessage response = await client.PutAsJsonAsync("api/Product", p);
- 第三步:服务端端点直接使用强类型
Product作为入参即可,不需要手动调用反序列化方法,ASP.NET Core 模型绑定会自动完成参数解析:
[HttpPut] public async Task<IActionResult> Put([FromBody]Product product) { // 参数解析完成后可直接使用product对象 if (!ModelState.IsValid) { return BadRequest(ModelState); } // 执行业务逻辑 return Ok(); }
可选特殊配置
如果你因为业务原因必须保留公共字段、不想改写为属性,可以在服务端Program.cs中配置JSON序列化选项,开启公共字段的序列化/反序列化支持:
builder.Services.AddControllers() .AddJsonOptions(options => { // 开启公共字段处理支持 options.JsonSerializerOptions.IncludeFields = true; });
如果客户端和服务端混用了不同的序列化库(比如客户端用Newtonsoft.Json、服务端用System.Text.Json),要注意对齐命名策略、日期格式、空值处理等序列化配置,避免出现字段匹配失败的问题,最稳妥的方式是直接使用PutAsJsonAsync内置的序列化逻辑,不要手动拼接序列化内容。
内容的提问来源于stack exchange,提问作者user8149311
相关产品推荐
相关产品推荐

