Wie bekomme ich JSON in .NET mit C # formatiert?


256

Ich verwende den .NET JSON-Parser und möchte meine Konfigurationsdatei serialisieren, damit sie lesbar ist. Also statt:

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

Ich hätte gerne etwas Schöneres wie:

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

Mein Code ist ungefähr so:

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

Antworten:


257

Mit JavaScriptSerializer wird es Ihnen schwer fallen, dies zu erreichen.

Versuchen Sie es mit JSON.Net .

Mit geringfügigen Änderungen aus dem JSON.Net-Beispiel

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

Ergebnisse

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

Dokumentation: Serialisieren Sie ein Objekt


Es gibt auch ein Beispiel für die Formatierung der JSON-Ausgabe in seinem Blog james.newtonking.com/archive/2008/10/16/…
R0MANARMY

15
@Brad Er zeigte absolut den gleichen Code, aber mit einem Modell
Mia

Die Idee ist also nur Formatierung.
Indentiert

Diese Methode erspart außerdem JSON-Formatfehler.
Anshuman Goel

173

Ein kürzerer Beispielcode für die Json.Net-Bibliothek

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

1
Sie können noch einen Schritt weiter gehen und eine Erweiterungsmethode erstellen. Machen Sie es öffentlich und ändern Sie die Signatur in FormatJson (diese Zeichenfolge json)
bdwakefield

129

Wenn Sie eine JSON-Zeichenfolge haben und diese "verschönern" möchten, diese aber nicht zu und von einem bekannten C # -Typ serialisieren möchten, reicht Folgendes aus (mithilfe von 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
Um nur eine Json-Saite zu verschönern, ist dies eine viel bessere Lösung als die anderen ...
Jens Marchewka

2
Die folgenden Anwendungsfälle JsonPrettify("null")JsonPrettify("\"string\"")
schlagen

1
Danke @Ekevoo, ich habe es auf meine vorherige Version zurückgesetzt!
Duncan Smart

@ DuncanSmart Ich liebe das! Diese Version erstellt viel weniger temporäre Objekte. Ich denke, es ist besser als das, was ich kritisiert habe, auch wenn diese Anwendungsfälle funktioniert haben.
Ekevoo

97

Kürzeste Version, um vorhandenes JSON zu verschönern: (Bearbeiten: Verwenden von JSON.net)

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

Eingang:

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

Ausgabe:

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

So drucken Sie ein Objekt hübsch aus:

JToken.FromObject(myObject).ToString()

4
Dies funktioniert auch ohne vorherige Kenntnis der Struktur des JSON. Und es ist die kürzeste Antwort hier
for

1
Dies funktioniert jedoch nur, wenn das json-Objekt kein Array ist. Wenn Sie wissen, dass es sich um ein Array handelt, können Sie stattdessen JArray.Parse verwenden.
Luke Z

3
Ah, guter Punkt, danke. Ich habe meine Antwort aktualisiert, um sie JTokenanstelle von zu verwenden JObject. Dies funktioniert mit Objekten oder Arrays, da dies JTokendie Vorgängerklasse für JObjectund ist JArray.
Asherber

Vielen Dank, Mann, ich habe ungefähr 2 Stunden verschwendet, um zu dieser Lösung zu gelangen ... Ich kann mir mein Leben ohne @stackoverflow nicht vorstellen ...
Rudresha Parameshappa

Ich bevorzuge diese wirklich gegenüber den anderen Antworten. Funktionscode und effektiv. Vielen Dank
Marc Roussel

47

Oneliner mit Newtonsoft.Json.Linq:

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

Ich bin damit einverstanden, dass dies die einfachste API zum Formatieren von JSON mit Newtonsoft ist
Ethan Wu

2
Konnte dies nicht in Newtonsoft.Json finden ... vielleicht habe ich eine ältere Version.
Cslotty

2
Es befindet sich im Namespace NewtonSoft.Json.Linq. Ich weiß das nur, weil ich auch danach gesucht habe.
Kapitän Kenpachi

12

Sie können die folgende Standardmethode verwenden, um Json zu formatieren

JsonReaderWriterFactory.CreateJsonWriter (Stream-Stream, Codierungscodierung, bool ownStream, bool indent, string indentChars)

Setzen Sie nur "indent == true"

Versuchen Sie so etwas

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

Achten Sie auf Linien

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

Für einige Arten von XML-Serialisierern sollten Sie InvariantCulture verwenden , um Ausnahmen während der Deserialisierung auf Computern mit unterschiedlichen regionalen Einstellungen zu vermeiden. Zum Beispiel ungültiges Format von double oder DateTime manchmal diese.

Zum Deserialisieren

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

Vielen Dank!


Hallo, @Makeman, haben Sie jemals Serialisierungsfehler reproduziert, die von verschiedenen Kulturen verursacht wurden? XmlJsonWriter / Reader-Konvertierungen scheinen alle kulturinvariant zu sein.
Olexander Ivanitskyi

Hallo, ich bin mir bei XmlJsonWriter / Reader nicht sicher, aber DataContractJsonSerializer verwendet Thread.CurrentThread.CurrentCulture. Fehler können auftreten, wenn Daten auf dem Computer A serialisiert, auf dem B jedoch mit anderen regionalen Einstellungen deserialisiert wurden.
Makeman

Ich habe DataContractJsonSerializerin Assembly dekompiliert System.Runtime.Serialization v.4.0.0.0, es gibt keine explizite Verwendung von CurrentCulture. Die einzige Verwendung einer Kultur ist CultureInfo.InvariantCulturedie XmlObjectSerializerinterne Methode der Basisklasse TryAddLineInfo.
Olexander Ivanitskyi

Vielleicht ist es mein Fehler. Ich werde es später überprüfen. Möglicherweise extrapoliere ich dieses Kulturproblem aus der Implementierung eines anderen Serializers.
Makeman

1
Ich habe die ursprüngliche Antwort bearbeitet. Scheint, dass DataContract-Serialisierer kulturunabhängig sind, aber Sie sollten darauf achten, kulturspezifische Fehler während der Serialisierung durch andere Arten von Serialisierern zu vermeiden. :)
Makeman

6

All dies kann in einer einfachen Zeile erfolgen:

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

1
Denken Sie daran, "using Newtonsoft.Json" hinzuzufügen
Ebube

Am besten antworte mein Freund.
RogerEdward

5

Hier ist eine Lösung mit der System.Text.Json- Bibliothek von 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());
}

Dies ist eine gute Lösung für diejenigen, die kein zusätzliches Paket kaufen können. Funktioniert gut.
Mark T

2

Zuerst wollte ich einen Kommentar unter Duncan Smart hinzufügen, aber leider habe ich noch nicht genug Ruf, um Kommentare zu hinterlassen. Also werde ich es hier versuchen.

Ich möchte nur vor Nebenwirkungen warnen.

JsonTextReader analysiert json intern in typisierte JTokens und serialisiert sie dann zurück.

Zum Beispiel, wenn Ihr ursprünglicher JSON war

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

Nach dem Verschönern bekommst du

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

Natürlich sind beide JSON-Zeichenfolgen gleichwertig und werden deserialisiert, um strukturell gleiche Objekte zu erhalten. Wenn Sie jedoch die ursprünglichen Zeichenfolgenwerte beibehalten müssen, müssen Sie dies berücksichtigen


Es gibt hier eine großartige Diskussion über dieses Detail ... github.com/JamesNK/Newtonsoft.Json/issues/862 Interessant, wie sich dieses Detail entwickelt hat. Ich habe etwas Neues über meinen primären JSON-Parser gelernt - Vielen Dank für Ihren Kommentar.
SQL Surfer

2

Mit 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

Das hat bei mir funktioniert. Für den Fall, dass jemand nach einer VB.NET-Version sucht.

@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

Der folgende Code funktioniert für mich:

JsonConvert.SerializeObject(JToken.Parse(yourobj.ToString()))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.