2010-04-18 17 views
153

Estoy usando el analizador .NET JSON y me gustaría serializar mi archivo de configuración para que sea legible. Así que en lugar de:¿Cómo obtengo el formato JSON en .NET usando C#?

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

me gustaría algo más agradable como:

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

Mi código es algo como esto:

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

Respuesta

177

Usted va a tener dificultades para llevar a cabo esto con JavaScriptSerializer.

Probar JSON.Net.

con modificaciones menores de ejemplo 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; } 
    } 
} 

Resultados

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

Documentación: Serialize an Object

+0

Hay también un ejemplo de formato a la salida JSON en su blog http://james.newtonking.com/archive/2008/ 10/16/asp-net-mvc-y-JSON-net.aspx – R0MANARMY

+13

@Brad Mostró absolutamente el mismo código, pero utilizando un modelo – Mia

105

Un código de ejemplo más corto para la biblioteca Json.Net

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

Si usted tiene una cadena JSON y quiere "embellecer", pero no quiere que serializar hacia y desde un C# tipo conocido entonces la siguiente hace el truco (usando 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

Sólo para embellecer una cadena JSON esta es una solución adecuada tanto que los otros ... –

+2

Los siguientes casos de uso se producirá un error: ' JsonPrettify ("nulo")' y 'JsonPrettify ("\" cadena \ "")' – Ekevoo

+1

Gracias @Ekevoo, he hizo rodar de nuevo a mi versión anterior! –

5

Usted puede utilizar siguiente método estándar para conseguir JSON

JsonReaderWriterFactory.CreateJsonWriter (flujo de corriente, la codificación de la codificación, bool ownsStream, guión bool, indentChars cadena)

establece Sólo formato "guión == true"

intentar algo como esto

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

Pague su atención a las líneas

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

Debe utilizar InvariantCulture para evitar una excepción durante la deserialización en los equipos con distintas configuraciones regionales. Por ejemplo, el formato no válido de double o DateTime a veces los causa.

Para deserializar

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

Gracias!

38

La versión más corta para preexcribe JSON existente: (edit: using JSON.net)

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

de entrada:

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

Salida:

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

Para bastante-imprimir un objeto:

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

Esto funciona incluso sin conocer la estructura del json de antemano. Y es la respuesta más corta aquí. – foresightyj

+1

Esto funciona, pero solo si el objeto json no es una matriz. Si sabes que será una matriz, podrías usar JArray.Parse en su lugar. –

+3

Ah, buen punto, gracias. He actualizado mi respuesta para usar 'JToken' en lugar de' JObject'. Esto funciona con objetos o matrices, ya que 'JToken' es la clase antecesora para' JObject' y 'JArray'. – asherber

1

En primer lugar quería añadir comentar bajo Duncan Smart post, pero desafortunadamente aún no tengo suficiente reputación como para dejar comentarios. Así que lo intentaré aquí.

sólo quiero advertir sobre los efectos secundarios.

JsonTextReader analiza internamente JSON en JTokens mecanografiados y luego los serialises espalda.

Por ejemplo si su JSON original

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

Después Prettify que presentamos lo

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

Por supuesto, tanto cadena JSON son equivalentes y se deserializar a objetos estructuralmente iguales, pero si usted necesita para preservar los valores de cadena original, es necesario tener esto en concideration

Cuestiones relacionadas