代码之家  ›  专栏  ›  技术社区  ›  theringostarrs

如何转义JSON字符串?

  •  70
  • theringostarrs  · 技术社区  · 15 年前

    是否有任何类/函数可用于简单的JSON转义?我宁愿不用自己写。

    12 回复  |  直到 7 年前
        1
  •  58
  •   David Walschots    7 年前

    我用 System.Web.HttpUtility.JavaScriptStringEncode

    string quoted = HttpUtility.JavaScriptStringEncode(input);
    
        2
  •  38
  •   Richard Ev    7 年前

    建立在 the answer by Dejan ,你能做的就是 import System.Web.Helpers .NET Framework assembly ,然后使用以下函数:

    static string EscapeForJson(string s) {
      string quoted = System.Web.Helpers.Json.Encode(s);
      return quoted.Substring(1, quoted.Length - 2);
    }
    

    这个 Substring 需要呼叫,因为 Encode 自动用双引号括住字符串。

        3
  •  38
  •   Dunc    6 年前

    对于那些使用Newtonsoft非常流行的Json.Net项目的用户来说,这项任务很简单:

    using Newtonsoft.Json;
    
    ....
    var s = JsonConvert.ToString(@"a\b");
    Console.WriteLine(s);
    ....
    

    此代码打印:

    “a\\b”

    也就是说,结果字符串值包含引号和转义反斜杠。

        4
  •  24
  •   Clive Paterson    11 年前

    是的,只需将以下函数添加到Utils类或其他内容:

        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();
        }
    
        5
  •  18
  •   JaredPar    11 年前

    我使用了以下代码来转义json的字符串值。 您需要将“”添加到以下代码的输出中:

    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();
    }
    
        6
  •  5
  •   Stefan Steiger Marco van de Voort    8 年前

    这里提供的方法是错误的。
    既然可以使用System.Web.HttpUtility.JavaScriptEncode,为什么还要冒险这么远呢?

    如果你在一个较低的框架上,你可以直接从mono复制过去

    由mono项目提供@ 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();
        }
    

    这可以压缩成

    // 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();
        }
    }
    
        7
  •  4
  •   Community CDub    7 年前

    我也建议使用 JSON.NET 提到了库,但如果必须在生成的JSON字符串中转义unicode字符(例如,uxxx格式),则可能必须自己转义。看一看 Converting Unicode strings to escaped ascii string 举个例子。

        8
  •  4
  •   Community CDub    7 年前

    我对其中一些答案进行了长串和短串的速度测试。克莱夫帕特森的 code 赢了一点,大概是因为其他人考虑了序列化选项。以下是我的结果:

    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
    

    下面是测试代码:

    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();
    }
    
        9
  •  3
  •   Dejan Scott Dorman    11 年前

    那么System.Web.Helpers.Json.Encode(…)呢(请参见 http://msdn.microsoft.com/en-us/library/system.web.helpers.json.encode(v=vs.111).aspx )?

        10
  •  2
  •   user2058470    11 年前
    String.Format("X", c);
    

    只输出:X

    请改为:

    string t = ((int)c).ToString("X");
    
    sb.Append("\\u" + t.PadLeft(4, '0'));
    
        11
  •  2
  •   Joshua Duxbury    6 年前

    我很好的一行,使用了JsonConvert,就像其他人一样,但是添加了子字符串来删除添加的引号和反斜杠。

     var escapedJsonString = JsonConvert.ToString(JsonString).Substring(1, JsonString.Length - 2);
    
        12
  •  0
  •   Joseph Yaduvanshi    15 年前

    有一个Json库在 Codeplex