Comment échapper à JSON string?

y a-t-il des classes/fonctions disponibles pour faciliter L'échappement JSON? Je préfère ne pas avoir à écrire mon propre.

62
demandé sur wonea 2009-08-07 03:40:42

11 réponses

j'utilise System.Web.HttpUtility.JavaScriptStringEncode

string quoted = HttpUtility.JavaScriptStringEncode(input);
36
répondu xmedeko 2017-04-24 09:25:56

en S'appuyant sur la réponse de Dejan , ce que vous pouvez faire est importer System.Web.Helpers .net Framework assembly , 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'appel Substring est requis, puisque Encode entoure automatiquement les cordes avec des guillemets doubles.

35
répondu Rok Strniša 2017-06-06 23:57:09

pour ceux qui utilisent le très populaire Json.Net projet de Newtonsoft la tâche est triviale:

using Newtonsoft.Json;

....
var s = JsonConvert.ToString("a\b");
Console.WriteLine(s);
....

ce code imprime:

"a\\b"

C'est-à-dire que la valeur résultante de la chaîne contient les guillemets ainsi que le antislash échappé.

21
répondu Dror Harari 2017-05-08 08:08:11

Yep, il suffit d'ajouter la fonction suivante à votre classe Utils ou quelque chose comme ça:

    public static string cleanForJSON(string s)
    {
        if (s == null || s.Length == 0) {
            return "";
        }

        char         c = '"151900920"';
        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();
    }
19
répondu Clive Paterson 2013-07-18 07:31:10

j'ai utilisé le code suivant pour échapper à la valeur de chaîne 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();
}
18
répondu Amit Bhagat 2013-08-09 15:09:58

je recommande aussi d'utiliser le JSON.NET bibliothèque mentionnée, mais si vous devez échapper caractères unicode (par exemple le format \uXXXX) dans la chaîne JSON résultante, vous pouvez avoir à le faire vous-même. Jetez un oeil à convertissant les chaînes Unicode en chaîne ASCII échappée pour un exemple.

4
répondu Kevin Hakanson 2017-05-23 12:03:03

j'ai fait des tests de vitesse sur certaines de ces réponses pour une longue chaîne et une courte chaîne. Clive Paterson code gagné par un bon bit, 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 d'essai:

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();
}
4
répondu innominate227 2017-05-23 12:26:25

Les méthodes proposées ici sont défectueux.

Pourquoi t'aventurer si loin alors que tu pourrais juste utiliser le système.Web.HttpUtility.JavaScriptEncode ?

si vous êtes sur un cadre inférieur, vous pouvez simplement le copier depuis mono

gracieuseté du mono-project @ 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();
    }

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();
    }
}
4
répondu Stefan Steiger 2016-09-16 09:55:21

Qu'en est-il du système?Web.Helper.Json.Encodage.(..) (voir http://msdn.microsoft.com/en-us/library/system.web.helpers.json.encode (v=111).aspx )?

3
répondu Dejan 2014-01-05 16:16:32
String.Format("X", c);

qui sort juste: X

essayez plutôt ceci:

string t = ((int)c).ToString("X");

sb.Append("\u" + t.PadLeft(4, '0'));
2
répondu user2058470 2013-12-26 21:05:48

il y a une bibliothèque Json à Codeplex

0
répondu Jim Schubert 2009-08-06 23:42:38