【问题标题】:How to escape JSON string?如何转义 JSON 字符串?
【发布时间】:2009-08-06 23:40:42
【问题描述】:

是否有任何类/函数可用于轻松进行 JSON 转义?我宁愿不用自己写。

【问题讨论】:

  • JsonConvert.ToString() 为我工作。
  • @MartinLottering 谢谢!!!我一直在寻找一种将 json 转换为格式化字符串的方法。以下答案均无效,但确实有效。

标签: c# json escaping


【解决方案1】:

我用System.Web.HttpUtility.JavaScriptStringEncode

string quoted = HttpUtility.JavaScriptStringEncode(input);

【讨论】:

  • 我用它来避免 VS2015 中缺少 System.Web.Helpers.Json.Encode,但它需要 (input, true) 参数来包含实际的引号。
  • 这是我缺少的链接
  • 我注意到这会将单引号 ' 编码为 \u0027。然而,单引号在 JSON 字符串中是有效的。
【解决方案2】:

对于那些使用 Newtonsoft 非常流行的 Json.Net 项目的人来说,任务是微不足道的:

using Newtonsoft.Json;

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

此代码打印:

"a\\b"

也就是说,生成的字符串值包含引号以及转义的反斜杠。

【讨论】:

  • 我无法重现此方法来反序列化编码和转义的 unc 路径。我的路径"WatchedPath": "\\\\myserver\\output" 变成了"\"\\\\\\\\myserver\\\\output\"",这是非常不可接受的。
  • 上述方法不适用于反序列化 - 当您想要手动创建 JSON 文本并且您有一个 C# 字符串并且需要将其正确表示为文本时使用它。
  • @slestak,我想我遇到了和你一样的问题。你找到解决办法了吗?
  • @GP24 IIRC,我没有。抱歉,我没有更多信息。
  • 没问题,谢谢回复。如果对您有帮助,我会这样做: yourAnnoyingDoubleEncodedString.Replace("\\\\", "\\").Replace("\\\"", "\"");
【解决方案3】:

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 会自动用双引号将字符串括起来。

【讨论】:

  • 看起来 System.Web.Helpers 在 .Net 4.0 之前不可用
  • ……在 Visual Studio 2015 中也没有了。
  • 这是 ASP.NET 网页 2.0 的一部分。它可以使用 NuGet 添加。它不是框架的一部分。
【解决方案4】:

是的,只需将以下函数添加到您的 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();
    }

【讨论】:

  • 为什么要转义/
  • 我知道这是一个旧的答案,我很高兴看到这是因为我不想依赖任何外部库,但我注意到控制字符的默认情况将总是返回“\\u000X”。我相信您需要先将 char 转换为 int。考虑将其替换为string t = "000" + ((int)c).ToString("X");
  • 正确的默认大小写必须是:t = "000" + String.Format("{0:X}",(int) c);
  • 我们真正想要的是“"\\u" + ((int)c).ToString("X4")(虽然我觉得两个Appends会更好)
【解决方案5】:

我使用以下代码来转义 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();
}

【讨论】:

  • 这真的拯救了我的一天。非常感谢!
  • 请勿在生产环境中使用此代码!这种 JSON 转义遗漏了重要的特殊字符。见:stackoverflow.com/a/33799784
  • 这段代码没有涵盖所有的特殊情况。不要在生产中使用。
  • 重新发明轮子,并在特殊情况下引入一些错误,不是一个好的答案
【解决方案6】:

在 .Net Core 3+ 和 .Net 5+ 中:

string escapedJsonString = JsonEncodedText.Encode(jsonString);

【讨论】:

  • 您需要提及的是,默认情况下这不会进行微不足道的转义,结果可能比您想要的要转义得多。例如,引号、三角括号和许多字母将被转换为 unicode 字符,并且只有在您在另一端取消转义时才能使用。
【解决方案7】:

这里提供的方法有问题。
当您可以使用 System.Web.HttpUtility.JavaScriptEncode 时,为什么要冒险这么远?

如果你在较低的框架上,你可以从单声道复制粘贴它

感谢单一项目@ 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();
    }
}

【讨论】:

  • 这也将转义三角括号。对于 HTML 中的 JS 很重要,但对于 JSON 编码本身并不重要。
【解决方案8】:

我还建议使用提到的JSON.NET 库,但如果您必须在生成的 JSON 字符串中转义 unicode 字符(例如 \uXXXX 格式),您可能必须自己做。以Converting Unicode strings to escaped ascii string 为例。

【讨论】:

    【解决方案9】:

    我针对长字符串和短字符串对其中一些答案进行了速度测试。 Clive Paterson 的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();
    }
    

    【讨论】:

      【解决方案10】:

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

       var escapedJsonString = JsonConvert.ToString(JsonString).Substring(1, JsonString.Length - 2);
      

      【讨论】:

      • 我认为你的意思是 var escapedJsonString = JsonConvert.ToString(JsonString).Substring(1, JsonString.Length); - 否则你从字符串的末尾砍掉 2 个字符。请记住,\" 是原始长度的附加字符。
      【解决方案11】:

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

      【讨论】:

        【解决方案12】:
        String.Format("X", c);
        

        那只是输出:X

        试试这个:

        string t = ((int)c).ToString("X");
        
        sb.Append("\\u" + t.PadLeft(4, '0'));
        

        【讨论】:

          【解决方案13】:

          Codeplex 有一个 Json 库

          【讨论】:

            【解决方案14】:

            我选择使用System.Web.Script.Serialization.JavaScriptSerializer

            我有一个小的静态助手类,定义如下:

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

            序列化任何我调用Serialization.ToJSON(itemToSerialize)的东西

            要反序列化,我只需调用Serialization.FromJSON&lt;T&gt;(jsonValueOfTypeT)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-09-17
              • 2013-05-26
              • 2014-01-31
              • 2013-09-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多