为何字典转JSON填充jQuery下拉框无法保留排序?如何解决?
问题原因及解决方案
问题根源
排序丢失的核心原因是普通Dictionary<string, string>不保证顺序稳定性,且JSON对象的键本身是无序的:
- .NET中传统
Dictionary(.NET Framework及部分.NET Core版本)不会严格保留插入顺序; - 即使按排序后的列表插入
Dictionary,序列化成JSON对象时,序列化器(如Newtonsoft.Json)默认会按键名排序,导致前端拿到的对象顺序被打乱; - jQuery的
$.each遍历JSON对象时,顺序由浏览器/JS引擎决定,无法保证和后端插入顺序一致。
解决方法:用有序列表替代Dictionary
要保留排序,后端应直接返回有序的列表结构(而非Dictionary),序列化成JSON数组后顺序会完整保留,前端遍历数组即可保证排序正确。
修改后的控制器代码
直接返回排序后的匿名对象列表(结构清晰,推荐):
public JsonResult GetRolesByGroupId(string groupCode) { var roleList = BusinessLayer.GetRoles() .Where(x => x.GroupCode == groupCode) .Select(i => new { Value = i.RoleId.ToString(), Text = i.RoleDesc }) .OrderBy(i => i.Text) .ToList(); return Json(roleList, JsonRequestBehavior.AllowGet); }
修改后的jQuery代码
后端返回JSON数组,遍历需访问数组元素的Value和Text属性:
$('#groupCodeList').on("change", function () { if ($('#groupCodeList option:selected').text() === "All") { $('#RoleId').empty(); $('#RoleId').append('<option value=""></option>'); $('#RoleId').append('<option value="">All</option>'); } else { if ($('#groupCodeList option:selected').text()) { $.getJSON(getRolesUrl, { groupCode: $('#groupCodeList').val() }, function (data) { $('#RoleId').empty(); $('#RoleId').append('<option value="">--Select--</option>'); // 遍历数组,按顺序添加选项 $.each(data, function (index, item) { $('#RoleId').append('<option value="' + item.Value + '">' + item.Text + '</option>'); }); }); } else { $('#RoleId').empty(); $('#RoleId').append('<option value=""></option>'); } } });
备选方案:返回KeyValuePair列表
如果需要严格的键值对结构,可返回List<KeyValuePair<string, string>>,效果一致:
public JsonResult GetRolesByGroupId(string groupCode) { var roleList = BusinessLayer.GetRoles() .Where(x => x.GroupCode == groupCode) .Select(i => new KeyValuePair<string, string>(i.RoleId.ToString(), i.RoleDesc)) .OrderBy(kv => kv.Value) .ToList(); return Json(roleList, JsonRequestBehavior.AllowGet); }
对应jQuery遍历代码调整为:
$.each(data, function(index, kv) { $('#RoleId').append('<option value="' + kv.Key + '">' + kv.Value + '</option>'); });
内容的提问来源于stack exchange,提问作者Sandy
相关产品推荐
相关产品推荐

