以人类可读的文本格式进行序列化

5
在.NET 2.0(C#)中,是否有一种像XmlSerializer一样将对象序列化为简单/可定制的人类可读格式(例如PXLS或JSON)的方法?我知道XML是人类可读的,但我正在寻找一些更少烦人冗余的东西,可以将其作为用户结果输出到控制台。
5个回答

7
在.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...


几分钟前,我使用Json.NET发现JSON不是最好的方法,因为它不支持枚举。结果是一个数字,也不太易读。 - Martin
好的,实现取决于你要序列化什么。如果只有一个类型和少量成员,为什么不重写“ToString”并返回一个string.Format,以任何你想要的格式? - ullmark

4
我在这里发现了一份详尽的文档:

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

这个有用的类库可以支持泛型。
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 - mrexodia

2
.Net内置的序列化选项有Xml、Xml-Soap和二进制。由于您排除了xml,而二进制又无法以人类可读方式显示,所以您将不得不自己开发。
在自己开发时,您有几个选择:
1.向类添加Utility或Extention方法,就像AviewAnew建议的那样 2.扩展System.Runtime.Serialization.Formatter/实现System.Runtime.Serialization.IFormatter 3.通过Google在线查找通用组件来完成您想要的功能。
请注意,第二个选项可以针对您的特定类进行专门设计(如果您不想这个选项能处理任何类的话),后两个选项并不是互斥的。
我曾经在寻找.Net JSON格式化程序时进行过搜索,那时确实有多种选择。然而,那次我最终选择了另一种方向。我只是对它们中的任何一个都不太有信心。也许其他人可以提供更具体的建议。JSON正在变得越来越重要,希望微软会很快在框架中包含对它的"原生"支持。

我可以编写自己的HumanSerializer,以反射给定的对象类型 - 但这将耗费太多时间。我认为之前可能已经有人解决了这个问题 - 但谷歌没有找到他或她。 - Martin

1

https://dev59.com/_HE85IYBdhLWcg3wr1ge#38538454

您可以使用以下标准方法获取格式化的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 来避免在具有不同区域设置的计算机上反序列化时出现异常。例如,doubleDateTime 的无效格式有时会导致此类异常。

用于反序列化

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

谢谢!


0

将一个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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接