POST返回[X].Name格式JSON时反序列化失败排查
解决JSON反序列化为
List<RegretLetterDetail>为空的问题 当前POST回传的JSON无法反序列化为List<RegretLetterDetail>,反序列化后对象始终为空,除反序列化环节外其余流程正常。相关代码定义如下:
类定义
public class RegretLetterDetail { public int PositionID { get; set; } [Display(Name = "Description of Position")] public string PositionReference { get; set; } public string PositionName { get; set; } public int PayrollNumber { get; set; } [Display(Name = "Name of Candidate")] public string PersonName { get; set; } public bool PersonSelected { get; set; } [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")] [Display(Name = "Send")] public DateTime DateSend { get; set; } public bool IsDeleted { get; set; } public bool Undelete { get; set; } [Display(Name = "Changed By")] public string ChangedBy { get; set; } public bool SendEmial { get; set; } public bool SendSMS { get; set; } }
原jQuery序列化方法
$.fn.serializeObject = function () { var o = {}; var a = this.serializeArray(); $.each(a, function () { if (o[this.name] !== undefined) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.value || ''; } }); return o; };
原Ajax回传代码
var DetailParam = "@Html.Raw(Url.Action("_RegretPersonSelect", "Home"))"; var DetailData = JSON.stringify($('#_PersondetailRegret').serializeObject()); $.ajax({ type: 'POST', url: DetailParam, data: DetailData, success: function (result) { $("#RegretLetterto").html(result); } });
生成的问题JSON字符串
"{\"__RequestVerificationToken\":\"ZQn4bLDapqavi7dagatgluRffgxJGSJYHlRdMOXyzHN_LLPKrDZjdDUTVwYiLaOd8oTnt1Tqzw0deLLADlZbtvGZdIhUIPPRBzmQx_grHnBCnk15qfHMN3rds9Xy7eQs0\", \"[0].PersonSelected\":[\"true\",\"false\"],\"[0].PayrollNumber\":\"100001\",\"[0].SendSMS\":[\"true\",\"false\"], \"[1].PersonSelected\":[\"true\",\"false\"],\"[1].PayrollNumber\":\"100002\",\"[1].SendSMS\":[\"true\",\"false\"], \"[2].PersonSelected\":[\"true\",\"false\"],\"[2].PayrollNumber\":\"100003\",\"[2].SendSMS\":[\"true\",\"false\"], \"[3].PersonSelected\":[\"true\",\"false\"],\"[3].PayrollNumber\":\"100005\",\"[3].SendSMS\":[\"true\",\"false\"], \"[4].PersonSelected\":[\"true\",\"false\"],\"[4].PayrollNumber\":\"100006\",\"[4].SendSMS\":[\"true\",\"false\"] }"
原反序列化代码
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); model = (List<RegretLetterDetail>)serializer.Deserialize( jsonString, typeof(List<RegretLetterDetail>));
问题根源
- JSON是带索引键的对象(如
[0].PersonSelected),而非List<T>预期的纯对象数组结构 - 布尔字段的值是数组(如
["true","false"])且为字符串类型,无法匹配类中的bool属性 - Ajax请求未指定
contentType: "application/json",后端默认按表单格式解析,无法正确识别JSON内容 - 额外的
__RequestVerificationToken字段混入JSON,干扰数组反序列化
具体修复步骤
1. 修正Ajax请求的Content-Type
添加contentType: "application/json",明确告诉后端接收的是JSON格式数据:
var DetailParam = "@Html.Raw(Url.Action("_RegretPersonSelect", "Home"))"; var DetailData = JSON.stringify($('#_PersondetailRegret').serializeToRegretList()); $.ajax({ type: 'POST', url: DetailParam, data: DetailData, contentType: "application/json", // 新增该行 headers: { // 把验证令牌移到请求头,避免混入业务JSON "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() }, success: function (result) { $("#RegretLetterto").html(result); } });
2. 重写前端序列化逻辑,生成正确数组格式
替换原serializeObject方法,直接生成符合要求的对象数组,并正确处理复选框布尔值:
$.fn.serializeToRegretList = function () { var items = []; // 假设每个候选人的字段都包裹在class为"regret-item"的容器内,需根据实际DOM结构调整 $('.regret-item', this).each(function() { var item = {}; $(this).find(':input').each(function() { // 去掉字段名中的索引前缀(如[0].) var fieldName = this.name.replace(/^\[\d+\]\./, ''); if (this.type === 'checkbox') { // 复选框直接存布尔值,而非字符串数组 item[fieldName] = this.checked; } else { item[fieldName] = this.value || ''; } }); items.push(item); }); return items; };
修改后生成的JSON应为标准数组结构:
[ {"PersonSelected":true,"PayrollNumber":"100001","SendSMS":false}, {"PersonSelected":false,"PayrollNumber":"100002","SendSMS":true} ]
3. 后端优化:自动绑定参数(推荐)
无需手动反序列化,让ASP.NET自动绑定List<RegretLetterDetail>参数,同时处理验证令牌:
[HttpPost] public ActionResult _RegretPersonSelect(List<RegretLetterDetail> model) { // 从请求头获取验证令牌并验证 var token = Request.Headers["RequestVerificationToken"]; if (!AntiForgery.Validate(token)) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } // 直接使用绑定后的model即可 // ...业务逻辑处理 return PartialView(model); }
如果必须手动反序列化,推荐使用Newtonsoft.Json(比JavaScriptSerializer更灵活):
using Newtonsoft.Json; // 确保传入的是纯数组JSON(已剥离验证令牌) var model = JsonConvert.DeserializeObject<List<RegretLetterDetail>>(jsonString);
4. 处理类中值类型字段的默认值
将类中的值类型字段改为可空类型,避免因前端未传入值导致反序列化报错:
public int? PositionID { get; set; } public int? PayrollNumber { get; set; } public DateTime? DateSend { get; set; }
内容的提问来源于stack exchange,提问作者Danie Schoeman
相关产品推荐
相关产品推荐

