【发布时间】:2008-11-03 14:25:02
【问题描述】:
.NET 2.0 (C#) 中是否有一种方法可以像使用 XmlSerializer 以简单/可定制的人类可读格式(例如看起来像 PXLS 或 JSON)一样序列化对象? 我也知道 XML 是人类可读的,我正在寻找一些冗余较少的东西,你可以将结果输出到控制台以供用户使用。
【问题讨论】:
标签: c# .net serialization .net-2.0
.NET 2.0 (C#) 中是否有一种方法可以像使用 XmlSerializer 以简单/可定制的人类可读格式(例如看起来像 PXLS 或 JSON)一样序列化对象? 我也知道 XML 是人类可读的,我正在寻找一些冗余较少的东西,你可以将结果输出到控制台以供用户使用。
【问题讨论】:
标签: c# .net serialization .net-2.0
要在 .NET 中序列化为 JSON,请执行以下操作:
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;
}
集合项需要具有“DataContract”属性,并且您希望序列化为 JSON 的每个成员都必须具有“DataMember”属性。
这可能仅适用于 .NET 3.5。但是 2.0 也有一个同样简单的版本...
【讨论】:
我在这里找到了一份详尽的文档:
使用这个有用的类(支持泛型)
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;
}
}
【讨论】:
Encoding.Default 不适用于非ASCII 文本,因为DataContractJsonSerializer.WriteObject 的(未记录的)实现使用硬编码的Encoding.UTF8。
.Net 的内置序列化选项是 Xml、Xml-Soap 和二进制。既然你已经排除了 xml 和二进制绝对不是人类可读的,你就必须自己动手。
当你自己滚动时,你有几个选择:
请注意,第二项可以专门针对您的特定班级(如果您不希望,它不必能够处理任何班级)并且后两项不是互斥的。
我过去曾搜索过 .Net JSON 格式化程序,而且肯定有多种选择。然而,那次我最终走向了不同的方向。我只是对他们中的任何一个都没有信心。也许其他人可以提供更具体的建议。 JSON 变得足够大,希望微软很快会在框架中包含对它的“本机”支持。
【讨论】:
https://stackoverflow.com/a/38538454/6627992
您可以使用以下标准方法来获取格式化的 Json
JsonReaderWriterFactory.CreateJsonWriter(Stream stream, Encoding encoding, bool ownsStream, bool indent, string indentChars)
只设置"indent==true"
试试这样的
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());
}
}
注意线条
var currentCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
....
Thread.CurrentThread.CurrentCulture = currentCulture;
您应该使用 InvariantCulture 以避免在具有不同区域设置的计算机上反序列化期间出现异常。例如,double 或 DateTime 的格式无效有时会导致它们。
用于反序列化
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);
}
}
谢谢!
【讨论】:
将 xsl 应用到您的 xml 以去除您不想看到的内容?
类似
<?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>
【讨论】: