Existe-t-il des classes / fonctions disponibles à utiliser pour une échappement JSON facile? Je préfère ne pas avoir à écrire le mien.
Existe-t-il des classes / fonctions disponibles à utiliser pour une échappement JSON facile? Je préfère ne pas avoir à écrire le mien.
Réponses:
j'utilise System.Web.HttpUtility.JavaScriptStringEncode
string quoted = HttpUtility.JavaScriptStringEncode(input);
System.Web.Helpers.Json.Encode
dans VS2015, mais il a besoin du (input, true)
paramètre pour inclure également les citations réelles.
Pour ceux qui utilisent le très populaire projet Json.Net de Newtonsoft, la tâche est triviale:
using Newtonsoft.Json;
....
var s = JsonConvert.ToString(@"a\b");
Console.WriteLine(s);
....
Ce code imprime:
"un B"
Autrement dit, la valeur de chaîne résultante contient les guillemets ainsi que la barre oblique inverse échappée.
"WatchedPath": "\\\\myserver\\output"
devient "\"\\\\\\\\myserver\\\\output\""
ce qui est assez inacceptable.
En vous basant sur la réponse de Dejan , vous pouvez importer System.Web.Helpers
l'assembly .NET Framework , puis utiliser la fonction suivante:
static string EscapeForJson(string s) {
string quoted = System.Web.Helpers.Json.Encode(s);
return quoted.Substring(1, quoted.Length - 2);
}
L' Substring
appel est obligatoire, car Encode
entoure automatiquement les chaînes de guillemets.
Oui, ajoutez simplement la fonction suivante à votre classe Utils ou quelque chose:
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);
J'ai utilisé le code suivant pour échapper à la valeur de chaîne pour json. Vous devez ajouter votre "" "à la sortie du code suivant:
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();
}
Les méthodes proposées ici sont défectueuses.
Pourquoi s'aventurer aussi loin alors que vous pourriez simplement utiliser System.Web.HttpUtility.JavaScriptEncode?
Si vous êtes sur un framework inférieur, vous pouvez simplement le copier-coller à partir du mono
Gracieuseté du mono-projet @ 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();
}
Cela peut être compacté en
// 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();
}
}
Je recommanderais également d'utiliser la bibliothèque JSON.NET mentionnée, mais si vous devez échapper des caractères unicode (par exemple au format \ uXXXX) dans la chaîne JSON résultante, vous devrez peut-être le faire vous-même. Jetez un œil à la conversion de chaînes Unicode en chaîne ascii échappée pour un exemple.
J'ai effectué des tests de vitesse sur certaines de ces réponses pour une longue chaîne et une courte chaîne. Le code de Clive Paterson a bien gagné, probablement parce que les autres prennent en compte les options de sérialisation. Voici mes résultats:
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
Et voici le code de test:
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();
}
Qu'en est-il de System.Web.Helpers.Json.Encode (...) (voir http://msdn.microsoft.com/en-us/library/system.web.helpers.json.encode(v=vs.111) .aspx )?
String.Format("X", c);
Cela sort juste: X
Essayez plutôt ceci:
string t = ((int)c).ToString("X");
sb.Append("\\u" + t.PadLeft(4, '0'));
J'ai une belle ligne, j'ai utilisé JsonConvert comme d'autres l'ont fait, mais j'ai ajouté une sous-chaîne pour supprimer les guillemets ajoutés et la barre oblique inverse.
var escapedJsonString = JsonConvert.ToString(JsonString).Substring(1, JsonString.Length - 2);
Dans .Net Core 3+ et .Net 5+:
string escapedJsonString = JsonEncodedText.Encode(jsonString);
Il y a une bibliothèque Json chez Codeplex
J'ai choisi d'utiliser System.Web.Script.Serialization.JavaScriptSerializer
.
J'ai une petite classe d'assistance statique définie comme suit:
internal static partial class Serialization
{
static JavaScriptSerializer serializer;
static Serialization()
{
serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
}
public static string ToJSON<T>(T obj)
{
return serializer.Serialize(obj);
}
public static T FromJSON<T>(string data)
{
if (Common.IsEmpty(data))
return default(T);
else
return serializer.Deserialize<T>(data);
}
}
Pour sérialiser tout ce que je viens d'appeler Serialization.ToJSON(itemToSerialize)
Pour désérialiser je viens d'appeler Serialization.FromJSON<T>(jsonValueOfTypeT)