2008-11-03 12 views
5

Czy istnieje sposób .NET 2.0 (C#) do serializacji obiektu, podobnie jak przy użyciu XmlSerializer w prostym/dostosowywalnym formacie czytelnym dla człowieka, który wygląda na przykład na PXLS lub JSON? Też wiem, że XML jest czytelny dla człowieka, szukam czegoś z mniej irytującą redundancją, coś, co możesz wyprowadzić na konsolę jako wynik dla użytkownika.Serialize w czytelnym dla człowieka formacie tekstowym

Odpowiedz

6

do serializacji do JSON w .NET to zrobić w następujący sposób:

public static string ToJson(IEnumerable collection) 
     { 
      DataContractJsonSerializer ser = new DataContractJsonSerializer(collection.GetType()); 
      string json; 
      using (MemoryStream m = new MemoryStream()) 
      { 
       XmlDictionaryWriter writer = JsonReaderWriterFactory.CreateJsonWriter(m); 
       ser.WriteObject(m, collection); 
       writer.Flush(); 

       json = Encoding.Default.GetString(m.ToArray()); 
      } 
      return json; 
     } 

Element zbiory muszą mieć atrybut „DataContract”, a każdy członek chcesz być szeregowane do JSON musi mieć " DataMember "attibute.

Jest możliwe, że działa to tylko dla .NET 3.5. Ale jest równie prosta wersja 2.0 aswell ...

+0

Kilka minut temu przy użyciu [Json.NET] (http://www.codeplex.com/Json) dowiedziałem się, że JSON nie jest najlepszym sposobem, aby to zrobić, ponieważ nie obsługuje Enums. Rezultatem jest liczba, która nie jest czytelna dla ludzi. – Martin

+0

Okej, cóż, implementacja zależy od tego, co serializujesz. Jeśli jest to tylko jeden typ z kilkoma członkami, dlaczego nie wystarczy przesłonić "ToString" i zwrócić ciąg.Format w dowolnym formacie, który chcesz – ullmark

1

Wbudowane opcje serializacji dla .Net to Xml, Xml-Soap i plik binarny. Ponieważ wykluczyłeś xml i plik binarny z pewnością nie jest czytelny dla człowieka, musisz przetworzyć własny.

Podczas toczenia własne, masz kilka opcji:

  • dodać metody użyteczne lub rozszerzeniem do klasy, jak AviewAnew zasugerował
  • Extend System.Runtime.Serialization.Formatter/Wdrażanie System.Runtime. Serialization.IFormatter
  • Znajdź ogólny komponent online przez Google, który zrobi to, co chcesz.

Należy pamiętać, że druga pozycja może być wyspecjalizowana dla danej klasy (nie musi być w stanie obsłużyć żadnej klasy, jeśli jej nie chcesz), a dwie ostatnie pozycje nie wykluczają się wzajemnie .

Szukałem formatera .NET JSON w przeszłości i na pewno istnieje wiele opcji. Jednak tym razem skończyłem w innym kierunku. Po prostu nie czułem się pewnie w żadnym z nich. Może ktoś inny może dostarczyć bardziej szczegółowe zalecenie. JSON staje się na tyle duży, że wkrótce Microsoft włączy do niego "natywne" wsparcie w ramach.

+0

Mógłbym napisać własny HumanSerializer że odzwierciedla typ obiektu, które zostały podane do niego - ale to zużywają zbyt dużo czasu. Myślałem, że już wcześniej może być ktoś, kto rozwiązał ten problem - ale google go nie znalazło. – Martin

4

znalazłem exaustive dokumentację tutaj:

http://pietschsoft.com/post/2008/02/NET-35-JSON-Serialization-using-the-DataContractJsonSerializer.aspx

z tej klasy modified (rodzajowych wsparcia)

using System.Runtime.Serialization; 
using System.Runtime.Serialization.Json; 

public class JSONHelper 
{ 
    public static string Serialize<T>(T obj) 
    { 
     DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType()); 
     MemoryStream ms = new MemoryStream(); 
     serializer.WriteObject(ms, obj); 
     string retVal = Encoding.Default.GetString(ms.ToArray()); 
     ms.Dispose(); 
     return retVal; 
    } 

    public static T Deserialize<T>(string json) 
    { 
     T obj = Activator.CreateInstance<T>(); 
     MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)); 
     DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType()); 
     obj = (T)serializer.ReadObject(ms); 
     ms.Close(); 
     ms.Dispose(); 
     return obj; 
    } 
} 
+1

Co z czytelnym dla człowieka formatem tekstu ? – MajesticRa

+0

Użycie 'Encoding.Default' nie działa dla tekstu innego niż ASCII, ponieważ (nieudokumentowana) implementacja' DataContractJsonSerializer.WriteObject' używa zakodowanego na sztywno 'Encoding.UTF8'. – mrexodia

2

https://stackoverflow.com/a/38538454/6627992

Możesz użyć następującej standardowej metody uzyskiwania sformatowanego Json

JsonReaderWriterFactory.CreateJsonWriter (strumień Stream, kodowanie Kodowanie, bool ownsStream, bool tiret indentChars String)

Tylko ustawić "wcięcie == true"

Spróbuj coś takiego

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

zwrócić uwagę do linii

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

należy użyć InvariantCulture, aby uniknąć wyjątków podczas deserializacji na komputerach z różnymi ustawieniami regionalnymi. Na przykład niepoprawny format double lub DateTime czasami je powoduje.

Na deserializacji

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

Dzięki!

0

Zastosuj XSL do xml, aby usunąć to, czego nie chcesz zobaczyć?

coś

<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="text" indent="yes"/> 
    <xsl:template match="*"> 
     <xsl:value-of select="name()" /><xsl:text> 
</xsl:text> 
     <xsl:apply-templates select="@*"/> 
<xsl:apply-templates select="*"/> 
    </xsl:template> 
    <xsl:template match="@*|text()|comment()|processing-instruction"> 
    <xsl:value-of select="name()" />:<xsl:value-of select="." /><xsl:text> 
</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 
Powiązane problemy