web-dev-qa-db-ja.com

JavaScriptを使用するためのC#での引用のエスケープ

JSON形式でクエリの結果を返すASP.Net Webハンドラーがあります。

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

問題は、返されるデータに引用符が含まれていることがあり、jsオブジェクトに適切に作成できるようにこれらをjavascriptエスケープする必要があることです。データ内で引用符を見つけ(引用符が毎回存在しない)、それらの前に「/」文字を配置する方法が必要です。

応答テキストの例(間違った):

{"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#にかなり慣れていないので(実際にはコーディング全般)、コード内の何か他のものが愚かに見える場合はお知らせください。

59
Jason

.net 4.0以降には、標準のHttpUtility.JavaScriptStringEncode

Lone Coderによって記述された初期の西風ソリューションについては非常にいいです

156
Yauhen.F

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();
}
34
Bryan Legend

JavaScriptSerializerクラスを見る必要があると思います。ずっと安定しており、あらゆる種類のデータやエスケープ文字などを正しく処理します。また、コードはずっときれいに見えます。

あなたの場合、クラスは次のようになります。

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

このメソッドは、正しくシリアル化されたJSON文字列を返します...たとえば、sthは次のようになります。

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

楽しんで! :)

11
Artiom Chilaru

Javascriptの文字列リテラルを正しくエスケープするには、最初にすべてのバックスラッシュ文字をエスケープしてから、引用符(または文字列区切り文字として使用する場合はアポストロフィ)をエスケープします。

だから、あなたが必要なのは:

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

私に飛び出すのは、ループで文字列連結を使用しているということです。スケーリングが非常に悪いため、これは悪いことです。 + =演算子は、既存の文字列の末尾に文字を追加しません(文字列は不変であり、変更できないため)。代わりに、文字列と追加された文字を新しい文字列にコピーします。毎回より多くのデータをコピーすると、eEveryの追加行はメソッドの実行時間を約2倍にします。代わりに、StringBuilderを使用して文字列を作成します。

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();
}
5
Guffa

なぜあなたはこれをしないのですか:

string correctResponseText = wrongResponseText.Replace("\"", "\\\"");
0
Kon
string.Replace(<mystring>, @"\"", @"\\"");
0
Kirtan

C#からhtmlタグに文字列を送信する必要がある場合に機能します。

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

HttpUtility.HtmlEncode
0
Sergio Cabral