C # kullanarak .NET biçimlendirilmiş JSON nasıl alabilirim?


257

.NET JSON ayrıştırıcı kullanıyorum ve okunabilir olması için yapılandırma dosyamı serileştirmek istiyorum. Yani yerine:

{"blah":"v", "blah2":"v2"}

Gibi güzel bir şey istiyorum:

{
    "blah":"v", 
    "blah2":"v2"
}

Kodum böyle bir şeydir:

using System.Web.Script.Serialization; 

var ser = new JavaScriptSerializer();
configSz = ser.Serialize(config);
using (var f = (TextWriter)File.CreateText(configFn))
{
    f.WriteLine(configSz);
    f.Close();
}

Yanıtlar:


258

Bunu JavaScriptSerializer ile yapmakta zorlanacaksınız.

JSON.Net'i deneyin .

JSON.Net örneğindeki küçük değişiklikler ile

using System;
using Newtonsoft.Json;

namespace JsonPrettyPrint
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Product product = new Product
                {
                    Name = "Apple",
                    Expiry = new DateTime(2008, 12, 28),
                    Price = 3.99M,
                    Sizes = new[] { "Small", "Medium", "Large" }
                };

            string json = JsonConvert.SerializeObject(product, Formatting.Indented);
            Console.WriteLine(json);

            Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
        }
    }

    internal class Product
    {
        public String[] Sizes { get; set; }
        public decimal Price { get; set; }
        public DateTime Expiry { get; set; }
        public string Name { get; set; }
    }
}

Sonuçlar

{
  "Sizes": [
    "Small",
    "Medium",
    "Large"
  ],
  "Price": 3.99,
  "Expiry": "\/Date(1230447600000-0700)\/",
  "Name": "Apple"
}

Belgeler: Bir Nesneyi Seri Hale Getirme



15
@Brad Kesinlikle aynı kodu gösterdi, ancak bir model kullanarak
Mia

Fikir sadece Biçimlendirme.Indented
FindOutIslamNow

Bu yöntem ayrıca bir kişinin JSON biçiminde hatalar yapmasını engeller.
Anshuman Goel

173

Json.Net kütüphanesi için daha kısa bir örnek kod

private static string FormatJson(string json)
{
    dynamic parsedJson = JsonConvert.DeserializeObject(json);
    return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}

1
Bunu bir adım daha ileri taşıyabilir ve bir uzantı yöntemi oluşturabilirsiniz; herkese açık yapın ve imzayı FormatJson (bu dize json) olarak değiştirin
bdwakefield

129

Bir JSON dizeniz varsa ve "önizleme" yapmak istiyorsanız, ancak bilinen bir C # türüne ve bu diziden serileştirmek istemiyorsanız, hile (JSON.NET kullanarak) yapar:

using System;
using System.IO;
using Newtonsoft.Json;

class JsonUtil
{
    public static string JsonPrettify(string json)
    {
        using (var stringReader = new StringReader(json))
        using (var stringWriter = new StringWriter())
        {
            var jsonReader = new JsonTextReader(stringReader);
            var jsonWriter = new JsonTextWriter(stringWriter) { Formatting = Formatting.Indented };
            jsonWriter.WriteToken(jsonReader);
            return stringWriter.ToString();
        }
    }
}

6
Sadece bir Json ipini güzelleştirmek için bu diğerlerinden çok daha uygun bir çözüm ...
Jens Marchewka

2
Aşağıdaki kullanım durumları başarısız olacaktır: JsonPrettify("null")veJsonPrettify("\"string\"")
Ekevoo

1
Teşekkürler @Ekevoo, önceki sürümüme geri aldım!
Duncan Smart

@DuncanSmart Bunu seviyorum! Bu sürüm çok daha az geçici nesne oluşturur. Bu kullanım durumları işe yarasa bile eleştirdiğimden daha iyi olduğunu düşünüyorum.
Ekevoo

97

Mevcut JSON'u güzelleştirmek için en kısa sürüm : (değiştir: JSON.net kullanarak)

JToken.Parse("mystring").ToString()

Giriş:

{"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } }}

Çıktı:

{
  "menu": {
    "id": "file",
    "value": "File",
    "popup": {
      "menuitem": [
        {
          "value": "New",
          "onclick": "CreateNewDoc()"
        },
        {
          "value": "Open",
          "onclick": "OpenDoc()"
        },
        {
          "value": "Close",
          "onclick": "CloseDoc()"
        }
      ]
    }
  }
}

İçin bir nesne bayağı-yazdırın:

JToken.FromObject(myObject).ToString()

4
Bu, json'un yapısını önceden bilmeden bile çalışır. Ve buradaki en kısa cevap。
foresightyj

1
Bu çalışır, ancak yalnızca json nesnesi bir dizi değilse. Bir dizi olacağını biliyorsanız, bunun yerine bize JArray.Parse olabilir.
Luke Z

3
Ah, iyi bir noktaya, teşekkürler. Bunun JTokenyerine kullanmak için cevabımı güncelledim JObject. Bu hem nesnelerle hem de dizilerle çalışır, çünkü JTokenhem JObjectve hem de atalarının sınıfıdır JArray.
Asherber

Çok teşekkürler, adamım bu çözüme ulaşmak için yaklaşık 2 saat harcadım ...
@staoverflow

Bunu gerçekten diğer cevaplara tercih ediyorum. Kısa kod ve etkilidir. Teşekkür ederim
Marc Roussel

47

Oneliner kullanarak Newtonsoft.Json.Linq:

string prettyJson = JToken.Parse(uglyJsonString).ToString(Formatting.Indented);

Bu Newtonsoft kullanarak JSON biçimlendirmek için en basit API olduğunu kabul ediyorum
Ethan Wu

2
Newtonsoft.Json bulamadım ... belki eski bir sürümü var.
cslotty

2
NewtonSoft.Json.Linq ad alanında. Bunu biliyorum, çünkü ben de aramaya gittim.
Kaptan Kenpachi

12

Biçimlendirilmiş Json almak için aşağıdaki standart yöntemi kullanabilirsiniz

JsonReaderWriterFactory.CreateJsonWriter (Akış akışı, Kodlama kodlaması, bool owStStream, bool girintisi, string indentChars)

Yalnızca "indent == true" olarak ayarlayın

Böyle bir şey dene

    public readonly DataContractJsonSerializerSettings Settings = 
            new DataContractJsonSerializerSettings
            { UseSimpleDictionaryFormat = true };

    public void Keep<TValue>(TValue item, string path)
    {
        try
        {
            using (var stream = File.Open(path, FileMode.Create))
            {
                //var currentCulture = Thread.CurrentThread.CurrentCulture;
                //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

                try
                {
                    using (var writer = JsonReaderWriterFactory.CreateJsonWriter(
                        stream, Encoding.UTF8, true, true, "  "))
                    {
                        var serializer = new DataContractJsonSerializer(type, Settings);
                        serializer.WriteObject(writer, item);
                        writer.Flush();
                    }
                }
                catch (Exception exception)
                {
                    Debug.WriteLine(exception.ToString());
                }
                finally
                {
                    //Thread.CurrentThread.CurrentCulture = currentCulture;
                }
            }
        }
        catch (Exception exception)
        {
            Debug.WriteLine(exception.ToString());
        }
    }

Dikkatlerinize dikkat edin

    var currentCulture = Thread.CurrentThread.CurrentCulture;
    Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
    ....
    Thread.CurrentThread.CurrentCulture = currentCulture;

Bazı xml-serileştiriciler için, farklı Bölgesel ayarlara sahip bilgisayarlarda serileştirme sırasında istisnadan kaçınmak için InvariantCulture kullanmalısınız . Örneğin, geçersiz çift biçim veya DateTime biçimi bazen bunlara neden olabilir.

Serileştirmeyi kaldırmak için

    public TValue Revive<TValue>(string path, params object[] constructorArgs)
    {
        try
        {
            using (var stream = File.OpenRead(path))
            {
                //var currentCulture = Thread.CurrentThread.CurrentCulture;
                //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

                try
                {
                    var serializer = new DataContractJsonSerializer(type, Settings);
                    var item = (TValue) serializer.ReadObject(stream);
                    if (Equals(item, null)) throw new Exception();
                    return item;
                }
                catch (Exception exception)
                {
                    Debug.WriteLine(exception.ToString());
                    return (TValue) Activator.CreateInstance(type, constructorArgs);
                }
                finally
                {
                    //Thread.CurrentThread.CurrentCulture = currentCulture;
                }
            }
        }
        catch
        {
            return (TValue) Activator.CreateInstance(typeof (TValue), constructorArgs);
        }
    }

Teşekkürler!


Merhaba, @Makeman, farklı kültürlerin neden olduğu serileştirme hatalarını hiç ürettiniz mi? XmlJsonWriter / Reader dönüşümlerinin hepsi kültür değişmez gibi görünüyor.
Olexander Ivanitskyi

Merhaba, XmlJsonWriter / Reader hakkında emin değilim, ancak DataContractJsonSerializer Thread.CurrentThread.CurrentCulture kullanır. Veriler makine A'da serileştirildiğinde, ancak B'de başka bir bölgesel ayarlarla serileştirildiğinde hatalar oluşabilir.
Makeman

DataContractJsonSerializerMontajda ayrıştırıldım System.Runtime.Serialization v.4.0.0.0, açık bir kullanımı yok CurrentCulture. Bir kültürün tek kullanımı CultureInfo.InvariantCulturetemel sınıf XmlObjectSerializer, iç yöntemdir TryAddLineInfo.
Olexander Ivanitskyi

Yani, belki de benim hatam. Daha sonra kontrol edeceğim. Mümkün, başka bir serileştiricinin uygulanmasından bu kültür sorununu tahmin ediyorum.
Makeman

1
Orijinal cevabı düzenledim. DataContract serileştiricilerinin kültürden bağımsız olduğu anlaşılıyor, ancak başka bir serileştirici tarafından serileştirme sırasında kültüre özgü hatalardan kaçınmaya dikkat etmelisiniz. :)
Makeman

6

Bütün bunlar basit bir çizgide yapılabilir:

string jsonString = JsonConvert.SerializeObject(yourObject, Formatting.Indented);

1
'Newtonsoft.Json'u kullanarak' eklemeyi unutmayın
Ebube

en iyi cevap arkadaşım.
RogerEdward

5

İşte Microsoft'un System.Text.Json kütüphanesini kullanan bir çözüm :

static string FormatJsonText(string jsonString)
{
    using var doc = JsonDocument.Parse(
        jsonString,
        new JsonDocumentOptions
        {
            AllowTrailingCommas = true
        }
    );
    MemoryStream memoryStream = new MemoryStream();
    using (
        var utf8JsonWriter = new Utf8JsonWriter(
            memoryStream,
            new JsonWriterOptions
            {
                Indented = true
            }
        )
    )
    {
        doc.WriteTo(utf8JsonWriter);
    }
    return new System.Text.UTF8Encoding()
        .GetString(memoryStream.ToArray());
}

Ek bir paket satın alamayanlar için iyi bir çözümdür. İyi çalışıyor.
Mark T

2

İlk önce Duncan Smart yazısı altında yorum eklemek istedim, ama ne yazık ki henüz yorum bırakmak için yeterli üne sahip değilim. Bu yüzden burada deneyeceğim.

Sadece yan etkiler hakkında uyarmak istiyorum.

JsonTextReader dahili olarak json'u yazılan JTokens olarak ayrıştırır ve sonra bunları tekrar serileştirir.

Örneğin, orijinal JSON'unuz

 { "double":0.00002, "date":"\/Date(1198908717056)\/"}

Sonra güzel olsun

{ 
    "double":2E-05,
    "date": "2007-12-29T06:11:57.056Z"
}

Elbette her iki json dizesi de eşdeğerdir ve yapısal olarak eşit nesnelere serileştirilir, ancak orijinal dize değerlerini korumanız gerekiyorsa, bunu bir araya getirmeniz gerekir.


Burada bu ayrıntı hakkında harika bir tartışma var ... github.com/JamesNK/Newtonsoft.Json/issues/862 Bu detayın nasıl geliştiği ilginç. Birincil json ayrıştırıcım hakkında yeni bir şey öğrendim - Yorumunuz için teşekkür ederim.
Sql Surfer

2

System.Text.JsonSet kullanarak JsonSerializerOptions.WriteIndented = true:

JsonSerializerOptions options = new JsonSerializerOptions { WriteIndented = true };
string json = JsonSerializer.Serialize<Type>(object, options);

2

netcoreapp3.1

var js = JsonSerializer.Serialize(obj, new JsonSerializerOptions {
             WriteIndented = true
         });

0

Bu benim için çalıştı. Birinin VB.NET sürümünü araması durumunda.

@imports System
@imports System.IO
@imports Newtonsoft.Json

Public Shared Function JsonPrettify(ByVal json As String) As String
  Using stringReader = New StringReader(json)

    Using stringWriter = New StringWriter()
      Dim jsonReader = New JsonTextReader(stringReader)
      Dim jsonWriter = New JsonTextWriter(stringWriter) With {
          .Formatting = Formatting.Indented
      }
      jsonWriter.WriteToken(jsonReader)
      Return stringWriter.ToString()
    End Using
  End Using
End Function

0

Aşağıdaki kod benim için çalışıyor:

JsonConvert.SerializeObject(JToken.Parse(yourobj.ToString()))
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.