Bagaimana cara saya mendapatkan JSON yang diformat di .NET menggunakan C #?


256

Saya menggunakan parser .NET JSON dan ingin membuat serial file config saya agar dapat dibaca. Jadi alih-alih:

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

Saya ingin sesuatu yang lebih baik seperti:

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

Kode saya kira-kira seperti ini:

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

Jawaban:


257

Anda akan mengalami kesulitan menyelesaikan ini dengan JavaScriptSerializer.

Coba JSON.Net .

Dengan sedikit modifikasi dari contoh JSON.Net

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

Hasil

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

Dokumentasi: Buat serialisasi sebuah Objek


Ada juga contoh memformat output json di blognya james.newtonking.com/archive/2008/10/16/…
R0MANARMY

15
@Brad Dia benar-benar menunjukkan kode yang sama, tetapi menggunakan model
Mia

Jadi idenya hanyalah Pemformatan.
Diindeks

Metode ini juga menghemat satu dari membuat kesalahan format JSON.
Anshuman Goel

173

Kode sampel yang lebih pendek untuk perpustakaan Json.Net

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

1
Anda benar-benar dapat mengambil langkah ini lebih jauh dan membuat metode ekstensi; buat publik dan ubah tanda tangan ke FormatJson (string ini json)
bdwakefield

129

Jika Anda memiliki string JSON dan ingin "mem-prettify" itu, tetapi tidak ingin membuat cerita bersambung ke dan dari tipe C # yang dikenal, maka yang berikut melakukan trik (menggunakan JSON.NET):

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
Untuk hanya mendandani senar Json, ini adalah solusi yang jauh lebih baik daripada yang lain ...
Jens Marchewka

2
JsonPrettify("null")JsonPrettify("\"string\"")
Kasing

1
Terima kasih @Ekevoo, saya telah mengembalikannya ke versi saya sebelumnya!
Duncan Smart

@DuncanSmart Saya suka ini! Versi itu menciptakan jauh lebih sedikit objek sementara. Saya pikir itu lebih baik daripada yang saya kritik bahkan jika kasus penggunaan itu berhasil.
Ekevoo

97

Versi terpendek untuk membuat cantik JSON yang ada: (edit: using JSON.net)

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

Memasukkan:

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

Keluaran:

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

Untuk mencetak objek dengan cantik:

JToken.FromObject(myObject).ToString()

4
Ini berfungsi bahkan tanpa mengetahui struktur json sebelumnya. Dan ini adalah jawaban terpendek di sini。
foresightyj

1
Ini berfungsi, tetapi hanya jika objek json bukan array. Jika Anda tahu itu akan menjadi array Anda bisa menggunakan JArray.Parse sebagai gantinya.
Luke Z

3
Ah, poin bagus, terima kasih. Saya telah memperbarui jawaban saya untuk penggunaan JTokenbukan JObject. Ini berfungsi dengan objek atau array, karena JTokenmerupakan kelas leluhur untuk keduanya JObjectdan JArray.
asherber

Terima kasih banyak, kawan saya membuang waktu sekitar 2 jam untuk mendapatkan solusi ini ... Tidak dapat membayangkan hidup saya tanpa @stackoverflow ...
Rudresha Parameshappa

Saya benar-benar lebih suka yang ini daripada jawaban yang lain. Kode pendek dan efektif. Terima kasih
Marc Roussel

47

Oneliner menggunakan Newtonsoft.Json.Linq:

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

Saya setuju ini adalah API paling sederhana untuk memformat JSON menggunakan Newtonsoft
Ethan Wu

2
Tidak dapat menemukan ini di Newtonsoft.Json ... mungkin saya memiliki versi yang lebih lama.
cslotty

2
Ada di namespace NewtonSoft.Json.Linq. Saya hanya tahu ini karena saya juga mencarinya.
Kapten Kenpachi

12

Anda dapat menggunakan metode standar berikut untuk mendapatkan format Json

JsonReaderWriterFactory.CreateJsonWriter (Stream stream, Encoding encoding, bool memilikiStream, bool indent, string indentChars)

Hanya setel "indent == true"

Coba sesuatu seperti ini

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

Perhatikan baris Anda

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

Untuk beberapa jenis xml-serializers Anda harus menggunakan InvariantCulture untuk menghindari pengecualian selama deserialisasi pada komputer dengan pengaturan Regional yang berbeda. Misalnya, format ganda atau DateTime yang tidak valid terkadang menyebabkan mereka.

Untuk deserialisasi

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

Terima kasih!


Hai, Pakeman, apakah Anda pernah mereproduksi kesalahan serialisasi yang disebabkan oleh budaya yang berbeda? Sepertinya konversi XmlJsonWriter / Reader semuanya budaya invarian.
Olexander Ivanitskyi

Halo, saya tidak yakin tentang XmlJsonWriter / Reader, tetapi DataContractJsonSerializer menggunakan Thread.CurrentThread.CurrentCulture. Kesalahan dapat terjadi ketika data telah diserialisasi pada mesin A tetapi deserialized pada B dengan pengaturan regional lain.
Makeman

Saya didekompilasi DataContractJsonSerializerdalam perakitan System.Runtime.Serialization v.4.0.0.0, tidak ada penggunaan eksplisit CurrentCulture. Satu-satunya penggunaan budaya adalah CultureInfo.InvariantCulturedi kelas dasar XmlObjectSerializer, metode internal TryAddLineInfo.
Olexander Ivanitskyi

Jadi, mungkin itu kesalahanku. Saya akan memeriksanya nanti. Mungkin, saya meramalkan masalah budaya ini dari implementasi serializer lain.
Makeman

1
Saya telah mengedit jawaban asli. Tampaknya serialisator DataContract bersifat independen terhadap budaya, tetapi Anda harus menyimpan perhatian untuk menghindari kesalahan spesifik budaya selama serialisasi oleh jenis serialis lain. :)
Makeman

6

Semua ini dapat dilakukan dalam satu baris sederhana:

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

1
Ingatlah untuk menambahkan 'menggunakan Newtonsoft.Json'
Ebube

jawab teman saya yang terbaik.
RogerEdward

5

Berikut ini adalah solusi menggunakan perpustakaan System.Text.Json Microsoft :

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

Ini adalah solusi yang bagus untuk mereka yang tidak dapat membeli paket tambahan. Bekerja dengan baik.
Mark T

2

Pertama saya ingin menambahkan komentar di bawah posting Duncan Smart, tapi sayangnya saya belum punya reputasi yang cukup untuk meninggalkan komentar. Jadi saya akan mencobanya di sini.

Saya hanya ingin memperingatkan tentang efek samping.

JsonTextReader secara internal mem-parsing json ke dalam JTokens yang diketik dan kemudian membuat serial kembali.

Misalnya jika JSON asli Anda

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

Setelah cantik Anda dapatkan

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

Tentu saja kedua string json adalah setara dan akan deserialize ke objek yang sama secara struktural, tetapi jika Anda perlu mempertahankan nilai string asli, Anda harus mempertimbangkan ini.


Ada diskusi hebat tentang detail ini di sini ... github.com/JamesNK/Newtonsoft.Json/issues/862 Menarik bagaimana detail ini berkembang. Saya belajar sesuatu yang baru tentang json parser utama saya - Terima kasih atas komentar Anda.
Sql Surfer

2

Menggunakan System.Text.Jsonset 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

Ini berhasil untuk saya. Dalam kasus seseorang mencari versi VB.NET.

@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

Kode di bawah ini berfungsi untuk saya:

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