JSON dizesinden nasıl çıkılır?


102

Kolay JSON çıkışı için kullanılabilecek herhangi bir sınıf / işlev var mı? Kendi başıma yazmak zorunda kalmamayı tercih ederim.


4
JsonConvert.ToString () benim için çalıştı.
Martin Lottering

@MartinLottering Teşekkürler !!! Biçimlendirilmiş bir dizeye json almanın bir yolunu arıyordum. Aşağıdaki cevapların hiçbiri işe yaramadı ama bu işe yaradı.
GhostShaman

Yanıtlar:



50

Newtonsoft'un çok popüler Json.Net projesini kullananlar için görev önemsizdir:

using Newtonsoft.Json;

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

Bu kod şunları yazdırır:

"a \\ b"

Yani, sonuçta elde edilen dize değeri, tırnak işaretlerinin yanı sıra kaçan ters eğik çizgiyi içerir.


2
Kodlanmış ve öncelenmiş bir unc yolu serisini kaldırmak için bu yöntemi çoğaltamıyorum. Yolum oldukça kabul edilemez "WatchedPath": "\\\\myserver\\output"hale geliyor "\"\\\\\\\\myserver\\\\output\"".
slestak

3
Yukarıdaki yöntem seriyi kaldırmak için değildir - değerlendirici, manuel olarak bir JSON metni oluşturmak istediğinizde ve bir C # dizeniz olduğunda ve metin olarak uygun temsilini almanız gerektiğinde kullanılır.
Dror Harari

@slestak, sanırım burada olduğun sorunla karşılaşıyorum. bir çözüm buldun mu?
GP24

@ GP24 IIRC, yapmadım. Üzgünüm daha fazla bilgim yok.
slestak

Sorun değil, yanıtladığınız için teşekkürler. Size yardımcı oluyorsa bunu yaptım: yourAnnoyingDoubleEncodedString.Replace ("\\\\", "\\"). Değiştir ("\\\" "," \ "");
GP24

40

Dejan'ın cevabına dayanarak yapabilecekleriniz .NET Framework derlemesini içe aktarmakSystem.Web.Helpers ve ardından aşağıdaki işlevi kullanmaktır:

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

SubstringÇünkü çağrı gereklidir Encodeotomatik çift tırnak dizelerle çevreler.


Görünüşe göre System.Web.Helpers, .Net 4.0'dan önce kullanılamıyor
SerG

… Ve artık Visual Studio 2015'te yok.
lapo

5
Bu, ASP.NET Web Pages 2.0'ın bir parçasıdır. NuGet kullanılarak eklenebilir. Çerçevenin bir parçası değildir.
Murven

31

Evet, aşağıdaki işlevi Utils sınıfınıza veya başka bir şeye ekleyin:

    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
Neden kaçman gerekiyor /?
drzaus

Bunun eski bir cevap olduğunu biliyorum ve herhangi bir harici kütüphaneye güvenmek istemediğim için bunun verildiğini görmekten mutluyum, ancak bir kontrol karakteri için varsayılan durumun her zaman "\\ u000X" döndüreceğini fark ettim. İlk önce bir int'e karakter atmanız gerektiğine inanıyorum. Değiştirmeyi düşününstring t = "000" + ((int)c).ToString("X");
Ocak 2018, 19: 18'de Diskart

Doğru varsayılan durum şu şekilde olmalıdır:t = "000" + String.Format("{0:X}",(int) c);
daniatic

Aslında istediğimiz şey " "\\u" + ((int)c).ToString("X4") (İki Appends'ın daha da iyi olacağını düşünmeme rağmen)
James Curran

16

Aşağıdaki kodu json için dize değerinden kaçmak için kullandım. Aşağıdaki kodun çıktısına '"' eklemeniz gerekir:

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
Bu gerçekten günümü kurtardı. Çok teşekkürler!
casaout

8
Bu kodu üretimde kullanmayın! Bu JSON kaçışında önemli özel karakterler eksik. Bakınız: stackoverflow.com/a/33799784
vog

2
Bu kod tüm özel durumları kapsamaz. Üretimde KULLANMAYIN.
Envil

2
Tekerleği yeniden icat etmek ve özel durumlarda bazı hataları ortaya
çıkarmak

6

Burada sunulan yöntemler hatalı.
System.Web.HttpUtility.JavaScriptEncode kullanabiliyorken neden bu kadar uzağa gidelim?

Daha düşük bir çerçevedeyseniz, bunu monodan kopyalayıp yapıştırabilirsiniz.

Mono-projenin izniyle @ 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();
    }

Bu sıkıştırılabilir

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

Uzun bir dizi ve kısa bir dizi için bu cevapların bazıları üzerinde hız testleri yaptım. Clive Paterson'ın kodu , muhtemelen diğerleri serileştirme seçeneklerini hesaba kattığı için oldukça kazandı. İşte sonuçlarım:

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

Ve işte test kodu:

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

.Net Core 3+ ve .Net 5+ içinde:

string escapedJsonString = JsonEncodedText.Encode(jsonString);

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

Bu sadece çıktı: X

Bunun yerine şunu deneyin:

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

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

2

Güzel bir tek satırlık, diğerleri gibi JsonConvert'ı kullandım, ancak eklenen tırnak işaretlerini ve ters eğik çizgiyi kaldırmak için alt dizeyi ekledim.

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


0

Kullanmayı seçtim System.Web.Script.Serialization.JavaScriptSerializer.

Aşağıdaki gibi tanımlanmış küçük bir statik yardımcı sınıfım var:

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

Sadece aradığım her şeyi seri hale getirmek için Serialization.ToJSON(itemToSerialize)

Seri durumdan çıkarmak için aradım Serialization.FromJSON<T>(jsonValueOfTypeT)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.