Escape引用在C#中的JavaScript消费

我有一个ASP.Net Web处理程序返回JSON格式的查询结果

public static String dt2JSON(DataTable dt) { String s = "{\"rows\":["; if (dt.Rows.Count > 0) { foreach (DataRow dr in dt.Rows) { s += "{"; for (int i = 0; i < dr.Table.Columns.Count; i++) { s += "\"" + dr.Table.Columns[i].ToString() + "\":\"" + dr[i].ToString() + "\","; } s = s.Remove(s.Length - 1, 1); s += "},"; } s = s.Remove(s.Length - 1, 1); } s += "]}"; return s; } 

问题是,有时返回的数据中有引号,我需要javascript转义这些,以便它可以正确创build到一个js对象。 我需要一种方法来查找我的数据中的引号(引号不是每次都有),并在它们前面放置一个“/”字符。

示例响应文本(错误):

 {"rows":[{"id":"ABC123","length":"5""}, {"id":"DEF456","length":"1.35""}, {"id":"HIJ789","length":"36.25""}]} 

我需要逃避“所以我的回应应该是:

 {"rows":[{"id":"ABC123","length":"5\""}, {"id":"DEF456","length":"1.35\""}, {"id":"HIJ789","length":"36.25\""}]} 

另外,我对C#很陌生(编码一般真的),所以如果我的代码中的其他东西看起来愚蠢让我知道。

对于.net 4.0 +,有标准的HttpUtility.JavaScriptStringEncode

Lone Coder所描述的较早西风解决scheme相当不错

这里是一个有效和强大的方法,我发现在http://www.west-wind.com/weblog/posts/114530.aspx

 /// <summary> /// Encodes a string to be represented as a string literal. The format /// is essentially a JSON string. /// /// The string returned includes outer quotes /// Example Output: "Hello \"Rick\"!\r\nRock on" /// </summary> /// <param name="s"></param> /// <returns></returns> public static string EncodeJsString(string s) { StringBuilder sb = new StringBuilder(); sb.Append("\""); foreach (char c in s) { switch (c) { case '\"': sb.Append("\\\""); break; case '\\': sb.Append("\\\\"); break; case '\b': sb.Append("\\b"); break; case '\f': sb.Append("\\f"); break; case '\n': sb.Append("\\n"); break; case '\r': sb.Append("\\r"); break; case '\t': sb.Append("\\t"); break; default: int i = (int)c; if (i < 32 || i > 127) { sb.AppendFormat("\\u{0:X04}", i); } else { sb.Append(c); } break; } } sb.Append("\""); return sb.ToString(); } 

我想你应该看看JavaScriptSerializer类。 它更加稳定,并能够正确处理任何types的数据或转义字符等。此外,您的代码将看起来更清洁。

在你的情况下,你的课堂可以像这样:

 public static String dt2JSON(DataTable dt) { var rows = new List<Object>(); foreach(DataRow row in dt.Rows) { var rowData = new Dictionary<string, object>(); foreach(DataColumn col in dt.Columns) rowData[col.ColumnName] = row[col]; rows.Add(rowData); } var js = new JavaScriptSerializer(); return js.Serialize(new { rows = rows }); } 

这个方法会返回一个正确的序列化的jsonstring…例如,像这样:

 {"rows":[{"id":1,"name":"hello"},{"id":2,"name":"bye"}]} 

玩的开心! 🙂

要正确地转义Javascript的string文字,首先要转义所有的反斜杠字符,然后您将引号(或撇号,如果您使用它们作为string分隔符)转义。

所以,你需要的是:

 value.Replace("\\","\\\\").Replace("\"","\\\"") 

还有什么我跳出来是你在一个循环中使用string连接。 这很糟糕,因为它的规模很差。 + =运算符不会在现有string的末尾添加字符(因为string是不可变的,永远不能更改),而是将string和添加的字符复制到新的string中。 随着您每次复制越来越多的数据,每增加一行,该方法的执行时间就会大大加倍。 使用StringBuilder来构buildstring。

使用ColumnName属性来获取列的名称而不是ToString方法。 ToString方法返回Expression属性的值,如果它没有设置,它返回ColumnName属性。

 public static String dt2JSON(DataTable dt) { StringBuilder s = new StringBuilder("{\"rows\":["); bool firstLine = true; foreach (DataRow dr in dt.Rows) { if (firstLine) { firstLine = false; } else { s.Append(','); } s.Append('{'); for (int i = 0; i < dr.Table.Columns.Count; i++) { if (i > 0) { s.Append(','); } string name = dt.Columns[i].ColumnName; string value = dr[i].ToString(); s.Append('"') .Append(name.Replace("\\","\\\\").Replace("\"","\\\"")) .Append("\":\"") .Append(value.Replace("\\","\\\\").Replace("\"","\\\"")) .Append('"'); } s.Append("}"); } s.Append("]}"); return s.ToString(); } 
 string.Replace(<mystring>, @"\"", @"\\""); 

你为什么不这样做:

 string correctResponseText = wrongResponseText.Replace("\"", "\\\""); 

工作时,我需要从C#发送string到HTML标记。

 <buton onlick="alert('<< here >>')" /> HttpUtility.HtmlEncode 

那么,对于初学者来说,你不需要在键的引号。

 {rows:[,]} is valid. and you could dt.Table.Columns[i].ToString().Replace("\","") 

但是如果你想保留双引号,单引号的作用与JS中的双引号相同

否则,你可以做

 String.Format("{name: \"{0}\"}",Columns[i].ToString().Replace("\",""))