Gibt es Klassen / Funktionen, die für ein einfaches JSON-Escape verwendet werden können? Ich möchte lieber nicht meine eigenen schreiben müssen.
Gibt es Klassen / Funktionen, die für ein einfaches JSON-Escape verwendet werden können? Ich möchte lieber nicht meine eigenen schreiben müssen.
Antworten:
ich benutze System.Web.HttpUtility.JavaScriptStringEncode
string quoted = HttpUtility.JavaScriptStringEncode(input);
System.Web.Helpers.Json.Encode
in VS2015 zu vermeiden , aber der (input, true)
Parameter muss auch die tatsächlichen Anführungszeichen enthalten.
Für diejenigen, die das sehr beliebte Json.Net-Projekt von Newtonsoft verwenden, ist die Aufgabe trivial:
using Newtonsoft.Json;
....
var s = JsonConvert.ToString(@"a\b");
Console.WriteLine(s);
....
Dieser Code druckt:
"a \\ b"
Das heißt, der resultierende Zeichenfolgenwert enthält die Anführungszeichen sowie den maskierten Backslash.
"WatchedPath": "\\\\myserver\\output"
wird "\"\\\\\\\\myserver\\\\output\""
ziemlich inakzeptabel.
Aufbauend auf der Antwort von Dejan können Sie die .NET Framework-Assembly importierenSystem.Web.Helpers
und dann die folgende Funktion verwenden:
static string EscapeForJson(string s) {
string quoted = System.Web.Helpers.Json.Encode(s);
return quoted.Substring(1, quoted.Length - 2);
}
Der Substring
Aufruf ist erforderlich, da Encode
Zeichenfolgen automatisch in doppelte Anführungszeichen gesetzt werden.
Ja, fügen Sie Ihrer Utils-Klasse einfach die folgende Funktion hinzu oder so:
public static string cleanForJSON(string s)
{
if (s == null || s.Length == 0) {
return "";
}
char c = '\0';
int i;
int len = s.Length;
StringBuilder sb = new StringBuilder(len + 4);
String t;
for (i = 0; i < len; i += 1) {
c = s[i];
switch (c) {
case '\\':
case '"':
sb.Append('\\');
sb.Append(c);
break;
case '/':
sb.Append('\\');
sb.Append(c);
break;
case '\b':
sb.Append("\\b");
break;
case '\t':
sb.Append("\\t");
break;
case '\n':
sb.Append("\\n");
break;
case '\f':
sb.Append("\\f");
break;
case '\r':
sb.Append("\\r");
break;
default:
if (c < ' ') {
t = "000" + String.Format("X", c);
sb.Append("\\u" + t.Substring(t.Length - 4));
} else {
sb.Append(c);
}
break;
}
}
return sb.ToString();
}
/
?
string t = "000" + ((int)c).ToString("X");
t = "000" + String.Format("{0:X}",(int) c);
Ich habe folgenden Code verwendet, um den Zeichenfolgenwert für json zu umgehen. Sie müssen Ihr '"' zur Ausgabe des folgenden Codes hinzufügen:
public static string EscapeStringValue(string value)
{
const char BACK_SLASH = '\\';
const char SLASH = '/';
const char DBL_QUOTE = '"';
var output = new StringBuilder(value.Length);
foreach (char c in value)
{
switch (c)
{
case SLASH:
output.AppendFormat("{0}{1}", BACK_SLASH, SLASH);
break;
case BACK_SLASH:
output.AppendFormat("{0}{0}", BACK_SLASH);
break;
case DBL_QUOTE:
output.AppendFormat("{0}{1}",BACK_SLASH,DBL_QUOTE);
break;
default:
output.Append(c);
break;
}
}
return output.ToString();
}
Die hier angebotenen Methoden sind fehlerhaft.
Warum so weit gehen, wenn Sie nur System.Web.HttpUtility.JavaScriptEncode verwenden könnten?
Wenn Sie sich in einem niedrigeren Framework befinden, können Sie es einfach kopieren und aus Mono einfügen
Mit freundlicher Genehmigung des Monoprojekts @ https://github.com/mono/mono/blob/master/mcs/class/System.Web/System.Web/HttpUtility.cs
public static string JavaScriptStringEncode(string value, bool addDoubleQuotes)
{
if (string.IsNullOrEmpty(value))
return addDoubleQuotes ? "\"\"" : string.Empty;
int len = value.Length;
bool needEncode = false;
char c;
for (int i = 0; i < len; i++)
{
c = value[i];
if (c >= 0 && c <= 31 || c == 34 || c == 39 || c == 60 || c == 62 || c == 92)
{
needEncode = true;
break;
}
}
if (!needEncode)
return addDoubleQuotes ? "\"" + value + "\"" : value;
var sb = new System.Text.StringBuilder();
if (addDoubleQuotes)
sb.Append('"');
for (int i = 0; i < len; i++)
{
c = value[i];
if (c >= 0 && c <= 7 || c == 11 || c >= 14 && c <= 31 || c == 39 || c == 60 || c == 62)
sb.AppendFormat("\\u{0:x4}", (int)c);
else switch ((int)c)
{
case 8:
sb.Append("\\b");
break;
case 9:
sb.Append("\\t");
break;
case 10:
sb.Append("\\n");
break;
case 12:
sb.Append("\\f");
break;
case 13:
sb.Append("\\r");
break;
case 34:
sb.Append("\\\"");
break;
case 92:
sb.Append("\\\\");
break;
default:
sb.Append(c);
break;
}
}
if (addDoubleQuotes)
sb.Append('"');
return sb.ToString();
}
Dies kann verdichtet werden
// https://github.com/mono/mono/blob/master/mcs/class/System.Json/System.Json/JsonValue.cs
public class SimpleJSON
{
private static bool NeedEscape(string src, int i)
{
char c = src[i];
return c < 32 || c == '"' || c == '\\'
// Broken lead surrogate
|| (c >= '\uD800' && c <= '\uDBFF' &&
(i == src.Length - 1 || src[i + 1] < '\uDC00' || src[i + 1] > '\uDFFF'))
// Broken tail surrogate
|| (c >= '\uDC00' && c <= '\uDFFF' &&
(i == 0 || src[i - 1] < '\uD800' || src[i - 1] > '\uDBFF'))
// To produce valid JavaScript
|| c == '\u2028' || c == '\u2029'
// Escape "</" for <script> tags
|| (c == '/' && i > 0 && src[i - 1] == '<');
}
public static string EscapeString(string src)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int start = 0;
for (int i = 0; i < src.Length; i++)
if (NeedEscape(src, i))
{
sb.Append(src, start, i - start);
switch (src[i])
{
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;
case '\"': sb.Append("\\\""); break;
case '\\': sb.Append("\\\\"); break;
case '/': sb.Append("\\/"); break;
default:
sb.Append("\\u");
sb.Append(((int)src[i]).ToString("x04"));
break;
}
start = i + 1;
}
sb.Append(src, start, src.Length - start);
return sb.ToString();
}
}
Ich würde auch empfehlen, die erwähnte JSON.NET- Bibliothek zu verwenden. Wenn Sie jedoch Unicode-Zeichen (z. B. das Format \ uXXXX) in der resultierenden JSON-Zeichenfolge maskieren müssen, müssen Sie dies möglicherweise selbst tun. Ein Beispiel finden Sie unter Konvertieren von Unicode-Zeichenfolgen in maskierte ASCII-Zeichenfolgen .
Bei einigen dieser Antworten habe ich Geschwindigkeitstests für eine lange und eine kurze Zeichenfolge durchgeführt. Clive Patersons Code hat ein gutes Stück gewonnen, vermutlich weil die anderen Serialisierungsoptionen berücksichtigen. Hier sind meine Ergebnisse:
Apple Banana
System.Web.HttpUtility.JavaScriptStringEncode: 140ms
System.Web.Helpers.Json.Encode: 326ms
Newtonsoft.Json.JsonConvert.ToString: 230ms
Clive Paterson: 108ms
\\some\long\path\with\lots\of\things\to\escape\some\long\path\t\with\lots\of\n\things\to\escape\some\long\path\with\lots\of\"things\to\escape\some\long\path\with\lots"\of\things\to\escape
System.Web.HttpUtility.JavaScriptStringEncode: 2849ms
System.Web.Helpers.Json.Encode: 3300ms
Newtonsoft.Json.JsonConvert.ToString: 2827ms
Clive Paterson: 1173ms
Und hier ist der Testcode:
public static void Main(string[] args)
{
var testStr1 = "Apple Banana";
var testStr2 = @"\\some\long\path\with\lots\of\things\to\escape\some\long\path\t\with\lots\of\n\things\to\escape\some\long\path\with\lots\of\""things\to\escape\some\long\path\with\lots""\of\things\to\escape";
foreach (var testStr in new[] { testStr1, testStr2 })
{
var results = new Dictionary<string,List<long>>();
for (var n = 0; n < 10; n++)
{
var count = 1000 * 1000;
var sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = System.Web.HttpUtility.JavaScriptStringEncode(testStr);
}
var t = sw.ElapsedMilliseconds;
results.GetOrCreate("System.Web.HttpUtility.JavaScriptStringEncode").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = System.Web.Helpers.Json.Encode(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("System.Web.Helpers.Json.Encode").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = Newtonsoft.Json.JsonConvert.ToString(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("Newtonsoft.Json.JsonConvert.ToString").Add(t);
sw = Stopwatch.StartNew();
for (var i = 0; i < count; i++)
{
var s = cleanForJSON(testStr);
}
t = sw.ElapsedMilliseconds;
results.GetOrCreate("Clive Paterson").Add(t);
}
Console.WriteLine(testStr);
foreach (var result in results)
{
Console.WriteLine(result.Key + ": " + Math.Round(result.Value.Skip(1).Average()) + "ms");
}
Console.WriteLine();
}
Console.ReadLine();
}
Was ist mit System.Web.Helpers.Json.Encode (...) (siehe http://msdn.microsoft.com/en-us/library/system.web.helpers.json.encode(v=vs.111) .aspx )?
String.Format("X", c);
Das gibt nur aus: X.
Versuchen Sie stattdessen Folgendes:
string t = ((int)c).ToString("X");
sb.Append("\\u" + t.PadLeft(4, '0'));
Ich habe einen schönen Einzeiler verwendet, JsonConvert wie andere verwendet, aber Teilzeichenfolgen hinzugefügt, um die hinzugefügten Anführungszeichen und den umgekehrten Schrägstrich zu entfernen.
var escapedJsonString = JsonConvert.ToString(JsonString).Substring(1, JsonString.Length - 2);
In .Net Core 3+ und .Net 5+:
string escapedJsonString = JsonEncodedText.Encode(jsonString);
Es gibt eine Json-Bibliothek bei Codeplex