ASMX服务JSON序列化遇特殊字符致解析失败的解决方案咨询
问题根因分析
- 根本原因不是特殊字符不符合JSON规范,是响应编码错误、序列化输出不规范两个问题共同导致的,你当前的手动替换方案属于绕开核心问题,才会需要不断新增替换规则。
- 你现有代码里的两个致命错误:
- 响应仅设置了
application/json类型,未指定UTF-8编码,前端解析时用默认编码读取会导致特殊字符乱码,触发JSON格式错误 - 响应输出顺序错误:先执行
Response.Flush()再写内容,同时Content-Length计算的是字符串长度而非UTF8字节长度,特殊字符占多字节时会导致内容截断,解析失败
- 响应仅设置了
修复方案
方案1:保留特殊字符(推荐,不需要修改原始内容)
直接修复序列化和响应逻辑,正常Unicode字符完全符合JSON规范,前端插件原生支持:
try { List<CalendarEvent> pdetails = new List<CalendarEvent>(); using (SqlConnection con = new SqlConnection(constring)) { using (SqlCommand cmd = new SqlCommand("[recmgt].[getCalendarEntries]", con)) { cmd.CommandType = CommandType.StoredProcedure; SqlDataAdapter DA = new SqlDataAdapter(cmd); DataSet ds = new DataSet(); DA.Fill(ds); foreach (DataRow dr in ds.Tables[0].Rows) { CalendarEvent per = new CalendarEvent(); per.id = dr["ID"].ToString(); // 不需要清洗标题,直接赋值 per.Title = dr["Title"].ToString(); per.Starts = dr["Starts"].ToString(); per.Ends = dr["Ends"].ToString(); pdetails.Add(per); } } } // 用Newtonsoft.Json序列化,自动处理所有特殊字符转义 string strResponse = JsonConvert.SerializeObject(pdetails); // 转成UTF8字节数组计算正确长度 byte[] responseBytes = System.Text.Encoding.UTF8.GetBytes(strResponse); Context.Response.Clear(); Context.Response.ContentType = "application/json; charset=utf-8"; // 明确指定UTF8编码 Context.Response.AddHeader("content-length", responseBytes.Length.ToString()); Context.Response.BinaryWrite(responseBytes); // 直接输出字节数组,避免编码转换问题 Context.Response.Flush(); // 写内容后再刷响应 Context.Response.End(); } catch (Exception exc) { // 建议加日志,方便定位问题 }
方案2:统一转成ASCII字符(如果业务要求不允许特殊字符)
用.NET内置的Unicode规范化方法自动转换所有带重音的拉丁字符,不需要手动维护替换规则:
public string ConvertToAscii(string input) { if (string.IsNullOrEmpty(input)) return input; // 先将字符串转为分离重音标记的规范化形式 string normalized = input.Normalize(NormalizationForm.FormD); StringBuilder sb = new StringBuilder(); foreach (char c in normalized) { // 过滤掉所有重音标记类字符 if (System.Globalization.CharUnicodeInfo.GetUnicodeCategory(c) != System.Globalization.UnicodeCategory.NonSpacingMark) { // 可选:过滤掉所有非ASCII字符,不需要保留其他字符可去掉该判断 if (c < 128) { sb.Append(c); } } } // 处理剩余的非重音类特殊字符 return sb.ToString().Replace("/", "_").Replace(@"\", " ").Replace("–", "-").Replace("—", "-").Replace("£", ""); }
调用时只需要把原来的cleanTitle换成ConvertToAscii即可,所有é、ô之类的带重音字符会自动转为对应的ASCII字符,不需要手动新增规则。
内容的提问来源于stack exchange,提问作者thebigsc
相关产品推荐
相关产品推荐

