C# 中的转义引号用于 javascript 消费

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/806944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 01:59:56  来源:igfitidea点击:

Escape Quote in C# for javascript consumption

c#escaping

提问by

I have a ASP.Net web handler that returns results of a query in JSON format

我有一个 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;
}

The problem is that sometimes the data returned has quotes in it and I would need to javascript-escape these so that it can be properly created into a js object. I need a way to find quotes in my data (quotes aren't there every time) and place a "/" character in front of them.

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

Example response text (wrong):

示例响应文本(错误):

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

I would need to escape the " so my response should be:

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

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

Also, I'm pretty new to C# (coding in general really) so if something else in my code looks silly let me know.

另外,我对 C# 还很陌生(实际上是一般的编码),所以如果我的代码中的其他内容看起来很傻,请告诉我。

回答by Kon

Why don't you just do this:

你为什么不这样做:

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

回答by Kirtan

string.Replace(<mystring>, @"\"", @"\"");

回答by Chad Grant

Well, for starters you do not need quotes around the keys.

好吧,对于初学者来说,您不需要在键周围加上引号。

{rows:[,]} is valid.

and you could dt.Table.Columns[i].ToString().Replace("\","")

But if you want to retain the double quotes, single quote works the same way double quotes do in JS

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

Otherwise you could do

否则你可以做

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

回答by Guffa

To correctly escape a string literal for Javascript, you first escape all backslash characters, then you escape the quotation marks (or apostrophes if you use them as string delimiters).

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

So, what you need is:

所以,你需要的是:

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

What else jumps out to me is that you are using string concatenation in a loop. This is bad, as it scales very poorly. The += operator does not add characters at the end of the existing string (as strings are immutable and can never be changed), instead it copies the string and the added characters to a new string. As you copy more and more data each time, eEvery additional row roughly doubles the execution time of the method. Use a StringBuilder to build the string instead.

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

Use the ColumnNameproperty to get the name of a column rather than the ToStringmethod. The ToStringmethod returns the Expressionproperty value if it's set, only if that is not set does it return the ColumnNameproperty.

使用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();
}

回答by Bryan Legend

Here is an efficient and robust method that I found at http://www.west-wind.com/weblog/posts/114530.aspx

这是我在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();
}

回答by Artiom Chilaru

I think you should rather look at the JavaScriptSerializer class. It's a lot more stable, and will correctly handle any kind of data or escape characters etc. Also, your code will look a lot cleaner.

我认为您应该查看 JavaScriptSerializer 类。它更加稳定,可以正确处理任何类型的数据或转义字符等。此外,您的代码看起来会更干净。

In your case your class can look like this:

在您的情况下,您的课程可能如下所示:

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

This method will return a correctly serialized json string... For example, sth like this:

这个方法会返回一个正确序列化的 json 字符串......例如,像这样:

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

Have fun! :)

玩得开心!:)

回答by Yauhen.F

For .net 4.0 + there is standard HttpUtility.JavaScriptStringEncode

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

For earlier west wind solution described by Lone Coder is quite nice

对于 Lone Coder 描述的早期西风解决方案非常好

回答by Sergio Cabral

Works when i need send string from C# to html tag.

当我需要将字符串从 C# 发送到 html 标签时有效。

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

HttpUtility.HtmlEncode

回答by aloisdg moving to codidact.com

Here is a rework of @Bryan Legend's answer with Linq:

以下是@Bryan Legend 对 Linq 的回答:

public static string EncodeJavaScriptString(string s)
    => string.Concat(s.Select(c => {
        switch (c)
        {
            case '\"': return "\\"";
            case '\': return "\\";
            case '\b': return "\b";
            case '\f': return "\f";
            case '\n': return "\n";
            case '\r': return "\r";
            case '\t': return "\t";
            default: return (c < 32 || c > 127) && !char.IsLetterOrDigit(c) ? $"\u{(int)c:X04}" : c.ToString();
        }}));

Try it Online!

在线试用!

changelog:

变更日志:

  • Remove double quoting wrapping since I do it in the js
  • Use expression body
  • Use a cleaner switch
  • Use Linq
  • Add a check for Letter to allow é
  • 删除双引号包装,因为我是在 js 中做的
  • 使用表达式主体
  • 使用更清洁的开关
  • 使用 Linq
  • 添加对 Letter 的检查以允许 é