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 Ssortingng dt2JSON(DataTable dt) { Ssortingng 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 il faudrait que javascript échappe à celles-ci pour pouvoir les créer correctement dans un object js. J’ai besoin d’un moyen de trouver des citations dans mes données (les guillemets ne sont pas là à chaque fois) et de placer un caractère “/” devant eux.

Exemple de texte de réponse (faux):

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

Je devrais échapper à la “alors 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) alors si quelque chose d’autre dans mon code a l’air idiot, faites le moi savoir.

Pour .net 4.0 +, il y a HttpUtility.JavaScriptSsortingngEncode standard

Pour le vent d’ouest, la solution décrite par Lone Coder est plutôt agréable

Voici une méthode efficace et robuste que j’ai trouvée à http://www.west-wind.com/weblog/posts/114530.aspx

 ///  /// Encodes a ssortingng to be represented as a ssortingng literal. The format /// is essentially a JSON ssortingng. /// /// The ssortingng returned includes outer quotes /// Example Output: "Hello \"Rick\"!\r\nRock on" ///  ///  ///  public static ssortingng EncodeJsSsortingng(ssortingng s) { SsortingngBuilder sb = new SsortingngBuilder(); 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.ToSsortingng(); } 

Je pense que vous devriez plutôt regarder la classe JavaScriptSerializer. Il est beaucoup plus stable et traitera correctement tous les types de données ou caractères d’échappement, etc. De plus, votre code sera beaucoup plus propre.

Dans votre cas, votre classe peut ressembler à ceci:

 public static Ssortingng dt2JSON(DataTable dt) { var rows = new List(); foreach(DataRow row in dt.Rows) { var rowData = new Dictionary(); 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 comme ceci:

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

S’amuser! 🙂

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

Donc, vous avez besoin de:

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

Ce qui me saute aux yeux, c’est que vous utilisez la concaténation de chaînes dans une boucle. C’est mauvais, car il échoue 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. Lorsque vous copiez de plus en plus de données à chaque fois, la ligne supplémentaire eEvery double sensiblement le temps d’exécution de la méthode. Utilisez un SsortingngBuilder pour créer la chaîne à la place.

Utilisez la propriété ColumnName pour obtenir le nom d’une colonne plutôt que la méthode ToSsortingng . La méthode ToSsortingng renvoie la valeur de la propriété Expression si elle est définie, mais uniquement si elle n’est pas définie renvoie la propriété ColumnName .

 public static Ssortingng dt2JSON(DataTable dt) { SsortingngBuilder s = new SsortingngBuilder("{\"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(','); } ssortingng name = dt.Columns[i].ColumnName; ssortingng value = dr[i].ToSsortingng(); s.Append('"') .Append(name.Replace("\\","\\\\").Replace("\"","\\\"")) .Append("\":\"") .Append(value.Replace("\\","\\\\").Replace("\"","\\\"")) .Append('"'); } s.Append("}"); } s.Append("]}"); return s.ToSsortingng(); } 
 ssortingng.Replace(, @"\"", @"\\""); 

Pourquoi ne faites-vous pas ça:

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

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

  HttpUtility.HtmlEncode 

Eh bien, pour commencer, vous n’avez pas besoin de guillemets autour des clés.

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

Mais si vous souhaitez conserver les guillemets doubles, les guillemets simples fonctionnent de la même manière que les guillemets doubles dans JS

Sinon, vous pourriez faire

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