问题
Is there a way in .NET 2.0 (C#) to serialize object like you do using XmlSerializer in a simple / customizable human readable format thats for instance looks like PXLS or JSON? Also I know that XML is human readable, I'm looking for something with less annoying redundancy, something that you can output to the console as a result for the user.
回答1:
To Serialize into JSON in .NET you do as follows:
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;
}
The collections item need to have the "DataContract" attribute, and each member you wish to be serialized into the JSON must have the "DataMember" attibute.
It's possible that this only works for .NET 3.5. But there is an equally simple version for 2.0 aswell...
回答2:
I found a exaustive documentation here:
http://pietschsoft.com/post/2008/02/NET-35-JSON-Serialization-using-the-DataContractJsonSerializer.aspx
with this usefull class (support generics)
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;
}
}
回答3:
The built-in serialization options for .Net are Xml, Xml-Soap, and binary. Since you've ruled out xml and binary is definitely not human readable, you'll have to roll your own.
When rolling your own, you have a few options:
- Add Utility or Extention methods to the class, like AviewAnew suggested
- Extend System.Runtime.Serialization.Formatter / Implement System.Runtime.Serialization.IFormatter
- Find a generic component online via google that will do what you want.
Note that the 2nd item can be specialized for your specific class (it doesn't have to be able to handle any class, if you don't want it to) and the latter two items are not mutually exclusive.
I have searched for a .Net JSON formatter in the past, and there are definitely multiple options out there. However, I ended up going a different direction that time. I just didn't feel very confident in any of them. Maybe someone else can provide a more specific recommendation. JSON is becoming big enough that hopefully Microsoft will include "native" support for it in the framework soon.
回答4:
https://stackoverflow.com/a/38538454/6627992
You may use following standard method for getting formatted Json
JsonReaderWriterFactory.CreateJsonWriter(Stream stream, Encoding encoding, bool ownsStream, bool indent, string indentChars)
Only set "indent==true"
Try something like this
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());
}
}
Pay your attention to lines
var currentCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
....
Thread.CurrentThread.CurrentCulture = currentCulture;
You should use InvariantCulture to avoid exception during deserialization on the computers with different Regional settings. For example, invalid format of double or DateTime sometimes cause them.
For deserializing
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);
}
}
Thanks!
回答5:
Apply a xsl to your xml to strip out what you don't want to see ?
something like
<?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>
来源:https://stackoverflow.com/questions/258762/serialize-in-a-human-readable-text-format