【问题标题】:What is the most flexible serialization for .NET objects, yet simple to implement?.NET 对象最灵活的序列化是什么,但实现起来很简单?
【发布时间】:2010-09-11 12:27:43
【问题描述】:

我想序列化和反序列化对象,而不必担心整个类图。

灵活性是关键。我希望能够序列化传递给我的任何对象,而无需在整个对象图中使用完整的属性。

这意味着二进制序列化 不是一个选项,因为它只适用于 其他 .NET 平台。我会 也喜欢 a 可读的东西 人,因此可以被 管理方案及其他 口译员。

我在使用 DataContract、JSON 和 XML 序列化程序时发现了问题。

  • 这些错误中的大多数似乎都围绕列表/字典的序列化(即XML Serializable Generic Dictionary)。
  • "添加任何静态未知的类型 到已知类型的列表 - 对于 例如,通过使用 KnownTypeAttribute 属性或由 将它们添加到已知列表中 传递给的类型 DataContractSerializer。”

请根据实际经验而不是理论或阅读文章来回答。

【问题讨论】:

    标签: c# .net json serialization json.net


    【解决方案1】:

    您是否考虑过序列化为 JSON 而不是 XML?

    Json.NET 有一个非常强大和灵活的序列化程序,它对 Hashtables/通用字典没有问题,并且不需要任何特定属性。我知道是因为我写的:)

    它通过序列化程序上的各种选项为您提供大量控制,并允许您通过为其创建 JsonConverter 来覆盖类型的序列化方式。

    在我看来,JSON 比 XML 更具人类可读性,而 Json.NET 提供了编写格式良好的 JSON 的选项。

    最后,该项目是开源的,因此您可以在需要时单步执行代码并进行修改。

    【讨论】:

    • 我已经尝试过了,它给了我比开箱即用的 DataManinpulator JSON Serializer 更好的错误结果,但是由于循环引用,它仍然被炸毁。有小费吗?我正在构建一个消息传递框架,并且对任何对象的实际结构没有太多控制权。
    • 将 JsonSerializer 上的 ReferenceLoopHandling 属性设置为 Ignore。
    • 如果您想将对象转储到日志文件或控制台,这对于调试也非常方便。很棒的工具。
    【解决方案2】:

    如果我记得它对属性的作用是这样的:

    [XmlArray("Foo")]
    [XmlArrayItem("Bar")]
    public List<BarClass> FooBars
    { get; set; }
    

    如果你把它序列化,你会得到类似的东西:

    <Foo>
        <Bar />
        <Bar />
    </Foo>
    

    当然,我可能应该听从专家的意见。以下是来自 MS 的更多信息:http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayitemattribute.aspx

    让我知道这是否适合你。

    【讨论】:

      【解决方案3】:

      从您的要求看来,Xml 序列化是最好的。

      在序列化时,您对集合有哪些问题?如果您指的是不知道在 List 或类似的东西上使用什么属性,您可以尝试 您的财产上的 XmlArray 属性。你绝对可以序列化一个集合。

      【讨论】:

      • 您能否详细说明 XmlArray 属性...我在使用 Lists 时遇到问题...
      • 如果您使用 sgen,您实际上并不需要 XmlArray 属性。一般模式是从 List 派生一个单独的类,然后将其序列化,例如。 [Serializable] public class YourObjectCollection : List { } 但是,我发现即使这样也没有必要
      • +1 无知。修复了一个烦人的问题,即我无法序列化列表而没有额外的一组标签来包装它,因此我无法将它读取到 DataSet 中。
      【解决方案4】:

      XNA 框架中的 IntermediateSerializer 非常酷。你可以在http://blogs.msdn.com/shawnhar找到一堆使用它的教程

      【讨论】:

      【解决方案5】:

      SOAP 序列化对我来说效果很好,即使对于未标记为 [Serializable] 的对象也是如此

      【讨论】:

      【解决方案6】:

      如果集合中的对象包含对同一集合中其他对象的任何引用,您将遇到集合序列化问题。如果存在任何类型的双指向,您最终会创建一个无法序列化的多映射。在我序列化自定义集合的每一个问题上,总是因为我需要一些附加功能,这些功能作为“典型”客户端-服务器应用程序的一部分工作得很好,然后作为消费者提供者的一部分惨遭失败-服务器应用程序。

      【讨论】:

        【解决方案7】:

        把所有要序列化的类放到一个单独的程序集中,然后用sgen工具生成一个序列化程序集序列化成XML。使用 XML 属性来控制序列化。

        如果您需要自定义序列化程序集(并且您需要它来支持不是 IXmlSerializable 的类和包含抽象节点的类),然后指示 sgen 将源代码转储到单独的文件,然后将其添加到您的解决方案中。然后您可以根据需要对其进行修改。

        http://msdn.microsoft.com/en-us/library/bk3w6240(VS.80).aspx

        FWIW,我已经设法使用这种技术序列化整个 AdsML 框架(超过 400 个类)。它确实需要大量的手动定制,但如果您考虑框架的大小,就无法绕过这一点。 (我使用了一个单独的工具从 XSD 转到 C#)

        【讨论】:

          【解决方案8】:

          我同意基于 DataContract 的序列化方法(到 JSON、XML 等)比我想要的要复杂一些。

          如果您想获取 JSON,请查看 http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx

          它是 MS AJAX 扩展的一部分。诚然,它在 .NET 3.5 中被标记为已过时,但 ScottGu 在他的博客评论 (http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx#4301973) 中提到他不确定为什么,应该支持更长的时间。

          【讨论】:

            【解决方案9】:

            最简单的做法是使用 Serializable 属性标记您的对象,然后使用二进制格式化程序来处理序列化。如果任何包含的对象也被标记为可序列化,那么整个类图应该不成问题。

            【讨论】:

            • 不确定 mrbradleyt 说他不想担心时是否想忽略类图的某些部分。在这种情况下,并非所有属性都需要 Serializable(NonSerializedAttribute 可以标记应排除的字段)
            • 是的,重点。他还澄清说他需要一种非二进制格式,所以我的解决方案对他不起作用。
            • 提问者明确排除了二进制序列化。
            【解决方案10】:

            也许更有效的方法是使用 BinaryFormatter 进行序列化

            复制自http://blog.paranoidferret.com/index.php/2007/04/27/csharp-tutorial-serialize-objects-to-a-file/

            using System.IO;
            using System.Runtime.Serialization;
            using System.Runtime.Serialization.Formatters.Binary;
            
            public class Serializer
            {
               public Serializer()
               {
               }
            
               public void SerializeObject(string filename,
                              ObjectToSerialize objectToSerialize)
               {
                  Stream stream = File.Open(filename, FileMode.Create);
                  BinaryFormatter bFormatter = new BinaryFormatter();
                  bFormatter.Serialize(stream, objectToSerialize);
                  stream.Close();
               }
            
               public ObjectToSerialize DeSerializeObject(string filename)
               {
                  ObjectToSerialize objectToSerialize;
                  Stream stream = File.Open(filename, FileMode.Open);
                  BinaryFormatter bFormatter = new BinaryFormatter();
                  objectToSerialize =
                     (ObjectToSerialize)bFormatter.Deserialize(stream);
                  stream.Close();
                  return objectToSerialize;
               }
            }
            

            【讨论】:

              【解决方案11】:

              为了互操作性,我们一直使用 Xml 序列化,并确保我们的类从头开始设计以正确执行。

              我们创建一个 XSD 架构文档并使用 XSD.exe 从中生成一组类。这会生成部分类,因此我们然后创建一组相应的部分类来添加我们想要帮助我们填充类并在我们的应用程序中使用它们的额外方法(因为它们专注于序列化和反序列化并且有时使用起来有点困难)。

              【讨论】:

                【解决方案12】:

                您应该使用 NetDataContractSerializer。它涵盖了任何类型的对象图,并支持泛型、列表、多态(此处不需要 KnownType 属性)、递归等。 唯一的缺点是您必须使用 [Serializable] / [DataContract] 属性标记所有类,但经验表明您无论如何都必须进行某种手动微调,因为并非所有成员都应该被持久化。 它还序列化为 Xml,尽管它的可读性值得怀疑。

                我们的需求与您相同,因此选择了此解决方案。

                【讨论】:

                  猜你喜欢
                  • 2011-02-16
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-12-29
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多