2009-04-30 5 views
52

Ich habe eine ASP.Net Web-Handler, derFlucht Quote in C# für Javascript-Verbrauch

Ergebnisse einer Abfrage im JSON-Format zurückgibt
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; 
} 

Das Problem ist, dass manchmal die zurückgegebenen Daten Zitate in ihm hat und ich brauchen würde javascript-escape diese, so dass es ordnungsgemäß in ein js-Objekt erstellt werden kann. Ich brauche einen Weg, um Zitate in meinen Daten zu finden (Zitate sind nicht jedes Mal vorhanden) und platziere ein "/" vor ihnen.

Beispiel Antworttext (falsch):

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

ich müsste die "so meine Antwort sein sollte, entkommen:

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

Auch ich bin ziemlich neu in C# (Codierung in General wirklich) so, wenn etwas anderes in meinem Code sieht albern lassen Sie mich wissen

Antwort

0

Warum gehst du nicht einfach dies tun:.

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

+1 Gut gemacht. –

+8

Behandelt keine Daten mit anderen speziellen JS-Zeichen: Backslash, Zeilenumbruch, Wagenrücklauf. –

+1

Nicht wirklich so gut gemacht - wie David erwähnt hat, wird dies für viele andere Sonderzeichen nicht funktionieren. @Lone Coders Antwort ist besser. – zcrar70

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

Funktioniert nicht:' CS1056 Unerwartetes Zeichen '\' 'und' CS1003 Syntax error, ',' expected' – Sandro

-1

Nun, für den Anfang brauchen Sie keine Anführungszeichen um die Schlüssel.

{rows:[,]} is valid. 

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

Aber wenn man die doppelten Anführungszeichen, Apostroph funktioniert auf die gleiche Art und Weise doppelte Anführungszeichen tun in JS

Ansonsten behalten mögen Sie

tun könnten
String.Format("{name: \"{0}\"}",Columns[i].ToString().Replace("\","")) 
6

richtig Um einen Stringliteral für entkommen In JavaScript werden zuerst alle Backslash-Zeichen und anschließend die Anführungszeichen (oder Apostrophe, wenn sie als Trennzeichen für Zeichenfolgen verwendet werden) entfernt.

Also, was Sie brauchen, ist:

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

Was mir springt ist, dass Sie die String-Verkettung in einer Schleife verwenden. Das ist schlecht, da es sehr schlecht skaliert. Der Operator + = fügt keine Zeichen am Ende der vorhandenen Zeichenfolge hinzu (da Zeichenfolgen unveränderlich sind und nie geändert werden können), stattdessen werden die Zeichenfolge und die hinzugefügten Zeichen in eine neue Zeichenfolge kopiert. Wenn Sie jedes Mal mehr und mehr Daten kopieren, verdoppelt sich die Ausführungszeit der Methode in jeder zusätzlichen Zeile. Verwenden Sie stattdessen einen StringBuilder, um die Zeichenfolge zu erstellen.

Verwenden Sie die ColumnName-Eigenschaft, um den Namen einer Spalte anstelle der ToString-Methode abzurufen. Die ToString-Methode gibt den Eigenschaftswert Expression zurück, wenn sie festgelegt ist, nur wenn dies nicht festgelegt wird, gibt sie die ColumnName-Eigenschaft zurück.

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(); 
} 
+0

Wie zu decodieren? – MonsterMMORPG

+0

@MonsterMMORPG: Sie dekodieren es nicht, Sie analysieren es. Der Zweck des Escaping ist, damit der Code ordnungsgemäß analysiert werden kann Sobald die Daten analysiert sind, sind die Strings wieder in ihrer ursprünglichen Form. – Guffa

34

Hier ist eine effiziente und robuste Methode, die ich bei http://www.west-wind.com/weblog/posts/114530.aspx gefunden

/// <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(); 
} 
+3

Die Verwendung einer Methode wie dieser ist wichtig, um mögliche XSS-Angriffe zu vermeiden, die passieren könnten, wenn JSON evaluiert wird .. –

+1

Schön, ich habe eine zusätzliche case-Anweisung hinzugefügt codieren auch einfache Anführungszeichen –

+1

Ich glaube nicht, dass einfache Anführungszeichen in doppelte Anführungszeichen eingeschlossen werden müssen –

11

Ich glaube, Sie lieber an der JavaScriptSerializer Klasse aussehen sollten. Es ist viel stabiler und behandelt alle Arten von Daten oder Escape-Zeichen usw. korrekt. Außerdem wird Ihr Code viel sauberer aussehen.

In Ihrem Fall können Sie Ihre Klasse wie folgt aussehen:

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

Diese Methode wird ein richtig serialisierten JSON-String ... Zum Beispiel, etw wie folgt zurück:

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

Viel Spaß! :)

140

für .net 4.0 + es Standard ist HttpUtility.JavaScriptStringEncode

Für frühere Westwind Lösung von Lone Coder beschrieben ist ganz nett

+5

das hat mir gerade geholfen;) danke –

+0

Beste Antwort, danke –

+0

Ich arbeitete an Software mit Uri.EscapeDataString, die Probleme verursachte, wenn Zitate in der Zeichenfolge waren. Das Wechseln zu HttpUtility.JavaScriptStringEncode war die richtige Lösung. Sie verdecken die Charaktere anders. EscapeDataString ->% 25, ​​JavaScriptStringEncode -> \\ ".... Update. Am Ende brauchte ich beide zB Url.EscapeDataString (HttpUtility.JavaScriptStringEncode (str)), um eine API zu erhalten, um Anführungszeichen (") und den Prozentsatz zu akzeptieren Charakter. Es mag einen besseren Weg geben, aber hoffentlich wird dieser Kommentar jemandem helfen. – HockeyJ

0

funktioniert, wenn ich Zeichenfolge von C# zu HTML-Tag senden müssen.

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

HttpUtility.HtmlEncode