2010-04-18 17 views
153

Sto usando parser .NET JSON e vorrei serializzare il mio file di configurazione in modo che sia leggibile. Così, invece di:Come posso ottenere JSON formattato in .NET usando C#?

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

vorrei qualcosa di più simile:

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

Il mio codice è qualcosa di simile:

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

risposta

177

Si sta per avere un tempo difficile realizzare questo con JavaScriptSerializer.

Prova JSON.Net.

Con piccole modifiche da JSON.Net esempio

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

Risultati

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

Documentazione: Serialize an Object

+0

C'è anche un esempio di formattazione di output json sul suo blog http://james.newtonking.com/archive/2008/ 10/16/asp-net-mvc-and-json-net.aspx – R0MANARMY

+13

@Brad Ha mostrato assolutamente lo stesso codice, ma utilizzando un modello – Mia

105

Un codice di esempio più corto per la libreria Json.Net

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

Se si dispone di una stringa JSON e vuole "prettify", ma non si vuole puntate in e da un noto tipo C# allora la seguente fa il trucco (utilizzando 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(); 
     } 
    } 
} 
+1

Solo per stimolare una stringa Json questa è una soluzione molto corretta rispetto alle altre ... –

+2

I seguenti casi d'uso non funzioneranno: 'JsonPrettify (" null ")' e 'JsonPrettify (" \ "string \" ")' – Ekevoo

+1

Grazie a @Ekevoo, ho eseguito il rollback alla mia versione precedente! –

5

Si possono utilizzare i seguenti metodo standard per ottenere in formato JSON

JsonReaderWriterFactory.CreateJsonWriter (ruscello, codifica codifica, bool ownsStream, bool trattino, indentChars arco) Solo

impostato "trattino == true"

provare qualcosa di simile

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

Prestare l'attenzione alle linee

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

Si dovrebbe usare InvariantCulture per evitare un'eccezione durante la deserializzazione sui computer con diverse impostazioni regionali. Ad esempio, il formato non valido di doppio o DateTime a volte li causa.

Per deserializzazione

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

Grazie!

38

La versione più corta a priva il JSON esistente: (modifica: utilizzando JSON.net)

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

ingresso:

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

uscita:

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

Per pretty-stampa un oggetto:

JToken.FromObject(myObject).ToString() 
+1

Questo funziona anche senza conoscere la struttura del JSON in anticipo. Ed è la risposta più breve qui. – foresightyj

+1

Funziona, ma solo se l'oggetto json non è un array. Se sai che sarà un array potresti invece usarlo come JArray.Parse. –

+3

Ah, buon punto, grazie. Ho aggiornato la mia risposta per usare 'JToken' invece di' JObject'. Funziona con oggetti o matrici, poiché 'JToken' è la classe di antenati sia per' JObject' che 'JArray'. – asherber

1

Per prima cosa ho voluto aggiungere commentare sotto Duncan Smart post, ma sfortunatamente non ho ancora abbastanza reputazione per lasciare commenti. Quindi lo proverò qui.

Voglio solo mettere in guardia sugli effetti collaterali.

JsonTextReader analizza internamente json in JTokens digitato e quindi li serializza nuovamente.

Per esempio, se l'originale JSON era

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

Dopo abbellire si ottiene

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

Naturalmente entrambi stringa JSON sono equivalenti e si deserializzare oggetti strutturalmente uguali, ma se avete bisogno di conservare valori di stringa originali, è necessario prendere questo in considerazione

Problemi correlati