Bagaimana cara keluar dari string JSON?


101

Apakah ada kelas / fungsi yang tersedia untuk digunakan agar JSON mudah melarikan diri? Saya lebih suka tidak harus menulis sendiri.


4
JsonConvert.ToString () bekerja untuk saya.
Martin Lottering

@MartinLottering Terima kasih !!! Saya telah mencari cara untuk mendapatkan json ke string yang diformat. Tak satu pun dari jawaban di bawah ini berhasil, tetapi ini berhasil.
GhostShaman

Jawaban:



50

Bagi mereka yang menggunakan proyek Json.Net yang sangat populer dari Newtonsoft, tugasnya sepele:

using Newtonsoft.Json;

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

Kode ini mencetak:

"a \\ b"

Artinya, nilai string yang dihasilkan berisi tanda kutip serta garis miring terbalik yang lolos.


2
Saya tidak dapat mereproduksi metode ini untuk deserialisasi jalur uncode dan escape. Jalan saya "WatchedPath": "\\\\myserver\\output"menjadi "\"\\\\\\\\myserver\\\\output\""yang sangat tidak bisa diterima.
slestak

3
Metode di atas bukan untuk deserialisasi - penilai digunakan saat Anda ingin membuat teks JSON secara manual dan Anda memiliki string C # dan perlu mendapatkan representasi yang tepat sebagai teks.
Dror Harari

@slestak, saya pikir saya menghadapi masalah yang sama dengan Anda di sini. Apakah Anda menemukan solusinya?
GP24

@ GP24 IIRC, saya tidak. Maaf saya tidak punya info lebih lanjut.
slestak

Tidak masalah, terima kasih sudah membalas. Saya melakukan ini jika membantu Anda: yourAnnoyingDoubleEncodedString.Replace ("\\\\", "\\"). Replace ("\\\" "," \ "");
GP24

40

Membangun jawaban oleh Dejan , apa yang dapat Anda lakukan adalah mengimpor System.Web.Helpersrakitan .NET Framework , kemudian menggunakan fungsi berikut:

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

The Substringpanggilan diperlukan, karena Encodesecara otomatis mengelilingi string dengan tanda kutip ganda.


Sepertinya System.Web.Helpers tidak tersedia sebelum .Net 4.0
SerG

… Dan tidak ada lagi di Visual Studio 2015 juga.
lapo

5
Ini adalah bagian dari ASP.NET Web Pages 2.0. Itu dapat ditambahkan menggunakan NuGet. Ini bukan bagian dari kerangka kerja.
Murven

31

Ya, cukup tambahkan fungsi berikut ke kelas Utils Anda atau sesuatu:

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

3
Mengapa Anda perlu melarikan diri /?
drzaus

Saya tahu ini adalah jawaban lama dan saya senang melihat ini diberikan karena saya tidak ingin bergantung pada pustaka eksternal, tetapi saya perhatikan bahwa kasus default untuk karakter kontrol akan selalu mengembalikan "\\ u000X". Saya yakin Anda perlu memasukkan karakter pertama ke int. Pertimbangkan untuk menggantinya denganstring t = "000" + ((int)c).ToString("X");
Jan Discart

Kasus default yang benar harus:t = "000" + String.Format("{0:X}",(int) c);
daniatic

Apa yang sebenarnya kami inginkan adalah " "\\u" + ((int)c).ToString("X4") (Meskipun saya pikir dua Appends akan lebih baik)
James Curran

16

Saya telah menggunakan kode berikut untuk menghindari nilai string untuk json. Anda perlu menambahkan '"' Anda ke keluaran dari kode berikut:

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

1
Ini benar-benar menyelamatkan hariku. Terima kasih banyak!
casaout

8
Jangan gunakan kode ini dalam produksi! Pelolosan JSON ini melewatkan karakter khusus yang penting. Lihat: stackoverflow.com/a/33799784
vog

2
Kode ini tidak mencakup semua kasus khusus. JANGAN digunakan dalam produksi.
Envil

2
menemukan kembali roda, dan memperkenalkan beberapa bug dalam kasus khusus, bukanlah jawaban yang baik
Xilmiki

6

Metode yang ditawarkan di sini salah.
Mengapa menjelajah sejauh itu ketika Anda bisa menggunakan System.Web.HttpUtility.JavaScriptEncode?

Jika Anda menggunakan kerangka kerja yang lebih rendah, Anda cukup menyalin dan menempelkannya dari mono

Atas kebaikan 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();
    }

Ini bisa dipadatkan menjadi

// 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

Saya menjalankan tes kecepatan pada beberapa jawaban ini untuk string panjang dan string pendek. Kode Clive Paterson menang sedikit, mungkin karena yang lain mempertimbangkan opsi serialisasi. Ini hasil saya:

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

Dan inilah kode tesnya:

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


3

Di .Net Core 3+ dan .Net 5+:

string escapedJsonString = JsonEncodedText.Encode(jsonString);

2
String.Format("X", c);

Itu hanya menghasilkan: X

Coba ini sebagai gantinya:

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

sb.Append("\\u" + t.PadLeft(4, '0'));

2

Saya bagus satu baris, menggunakan JsonConvert seperti yang dimiliki orang lain tetapi menambahkan substring untuk menghapus tanda kutip dan garis miring terbalik yang ditambahkan.

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


0

Saya memilih untuk menggunakan System.Web.Script.Serialization.JavaScriptSerializer.

Saya memiliki kelas pembantu statis kecil yang didefinisikan sebagai berikut:

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

Untuk membuat serialisasi apa pun yang saya sebut saja Serialization.ToJSON(itemToSerialize)

Untuk menghilangkan rasa, saya hanya menelepon Serialization.FromJSON<T>(jsonValueOfTypeT)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.