web-dev-qa-db-fra.com

Escape Quote in C # pour la consommation de javascript

J'ai un gestionnaire Web ASP.Net qui renvoie les résultats d'une requête au format 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;
}

Le problème est que parfois les données renvoyées contiennent des guillemets et que j’aurais besoin de javascript-escape pour pouvoir les créer correctement dans un objet js. J'ai besoin d'un moyen de trouver des citations dans mes données (les citations ne sont pas là à chaque fois) et de placer un caractère "/" devant elles.

Exemple de texte de réponse (faux):

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

J'aurais besoin d'échapper au "donc ma réponse devrait être:

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

De plus, je suis assez nouveau en C # (codage en général, vraiment), donc si quelque chose d'autre dans mon code a l'air ridicule, faites-le moi savoir.

57
Jason

Pour .net 4.0 +, il existe une norme HttpUtility.JavaScriptStringEncode

Pour la solution de vent d’ouest décrite par Lone Coder, c’est assez

153
Yauhen.F

Voici une méthode efficace et robuste que j'ai trouvée sur 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

Je pense que vous devriez plutôt regarder la classe JavaScriptSerializer. Il est beaucoup plus stable et gérera correctement tout type de données, de caractères d'échappement, etc. De plus, votre code sera beaucoup plus propre.

Dans votre cas, votre classe peut ressembler à ceci:

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

Cette méthode retournera une chaîne json correctement sérialisée ... Par exemple, sth ressemble à ceci:

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

S'amuser! :)

11
Artiom Chilaru

Pour échapper correctement à un littéral de chaîne pour Javascript, vous échappez tout d'abord aux barres obliques inverses, puis aux guillemets (ou aux apostrophes si vous les utilisez comme séparateurs de chaîne).

Alors, ce dont vous avez besoin c'est:

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

Ce qui me saute à l’esprit, c’est que vous utilisez la concaténation de chaînes dans une boucle. C'est mauvais, car ça pèse très mal. L'opérateur + = n'ajoute pas de caractères à la fin de la chaîne existante (les chaînes étant immuables et ne pouvant jamais être modifiées), il copie la chaîne et les caractères ajoutés dans une nouvelle chaîne. Au fur et à mesure que vous copiez de plus en plus de données, chaque ligne supplémentaire double grossit approximativement le temps d'exécution de la méthode. Utilisez plutôt un StringBuilder pour construire la chaîne.

Utilisez la propriété ColumnName pour obtenir le nom d'une colonne plutôt que la méthode ToString. La méthode ToString renvoie la valeur de la propriété Expression si elle est définie. Si elle ne l'est pas, elle renvoie la propriété 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

Pourquoi ne fais-tu pas ça:

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

Fonctionne lorsque j’ai besoin d’envoyer une chaîne de C # en balise HTML.

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

HttpUtility.HtmlEncode
0
Sergio Cabral