You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>));

问题根源

  1. JSON是带索引键的对象(如[0].PersonSelected),而非List<T>预期的纯对象数组结构
  2. 布尔字段的值是数组(如["true","false"])且为字符串类型,无法匹配类中的bool属性
  3. Ajax请求未指定contentType: "application/json",后端默认按表单格式解析,无法正确识别JSON内容
  4. 额外的__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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 04:13:11